0%

python面向对象

看fair gym然后发现我对python里的继承的用法有些误解

使用教程 https://www.liaoxuefeng.com/wiki/1016959663602400/1017495723838528

想要学到知识

  • [x] 继承是继承哪些东西,方法和属性?
  • [x] 有没有private类
  • [ ] 怎么选择继承

class

所有类最终的父类都是object

如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问

看到 https://blog.csdn.net/brucewong0516/article/details/79119551 中提到实例方法、静态方法和类方法

实例方法

第一个参数self,可以通过self访问类属性,这个好像我自己常用的方法

静态方法

定义的时候使用@staticmethod装饰器,打开了新世界,。。。不需要实例参数也不需要类参数

看起来很迷幻。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class person(object):
tall = 180
hobbies = []
def __init__(self, name, age,weight):
self.name = name
self.age = age
self.weight = weight
@staticmethod #静态方法装饰器
def infoma(): #没有参数限制,既不要实例参数,也不用类参数
print(person.tall)
print(person.hobbies)
#person.infoma() #静态法可以通过类名访问
Bruce = person("Bruce", 25,180) #通过实例访问
Bruce.infoma()

类方法

类方法以cls作为第一个参数cls表示类本身,定义时使用@classmethod装饰器。通过cls可以访问类的相关属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class person(object):
tall = 180
hobbies = []
def __init__(self, name, age,weight):
self.name = name
self.age = age
self.weight = weight
@classmethod #类的装饰器
def infoma(cls): #cls表示类本身,使用类参数cls
print(cls.__name__)
print(dir(cls))
#cls表示类本身
#person.infoma() 直接调用类的装饰器函数,通过cls可以访问类的相关属性
Bruce = person("Bruce", 25,180) #也可以通过两步骤来实现,第一步实例化person,第二步调用装饰器
Bruce.infoma()

就像学了假python

继承

继承很简单,在定义子类的时候把父类放在括号里就可以

父类的方法和属性都会被继承

子类自定义属性、方法可以覆盖父类,实现多态

这个时候如果要访问父类的属性,可以使用直接通过父类名调用,需要把self传进去不过(有点神奇,这个self应该是子类,相当于把子类传到了父类?)。

但是这样需要父类名硬编码到子类(忘了啥是硬编码了),所以推荐使用super

super(Child,self),第一个参数子类,第二个参数父类

装饰器

这个东西很有趣,顺便学一下, https://foofish.net/python-decorator.html

装饰器本质上是一个 Python 函数或类,它可以让其他函数或类在不需要做任何代码修改的前提下增加额外功能,装饰器的返回值也是一个函数/类对象。

1
2
3
4
5
6
7
8
9
def use_logging(func):
def wrapper():
logging.warn("%s is running" % func.__name__)
return func() # 把 foo 当做参数传递进来时,执行func()就相当于执行foo()
return wrapper
def foo():
print('i am foo')
foo = use_logging(foo) # 因为装饰器 use_logging(foo) 返回的时函数对象 wrapper,这条语句相当于 foo = wrapper
foo() # 执行foo()就相当于执行 wrapper()

有点意思,层层套娃

1
2
3
4
5
6
7
8
9
def use_logging(func):
def wrapper():
logging.warn("%s is running" % func.__name__)
return func()
return wrapper
@use_logging
def foo():
print("i am foo")
foo()

这里这个@就替代了上面的foo=use_logging(foo)

注意这里的foo()是没有参数的

如果有多个参数

1
2
3
4
def wrapper(*args):
logging.warn("%s is running" % func.__name__)
return func(*args)
return wrapper

foo 函数还定义了一些关键字参数呢?

1
2
3
4
5
def wrapper(*args, **kwargs):
# args是一个数组,kwargs一个字典
logging.warn("%s is running" % func.__name__)
return func(*args, **kwargs)
return wrapper

奇怪的知识又增加了

装饰器还可以带参数(暂时不记。


分割,上面讲的是函数的装饰器

还有类装饰器

使用类装饰器主要依靠类的__call__方法,当使用 @ 形式将装饰器附加到函数上时,就会调用此方法。

1
2
3
4
5
6
7
8
9
10
11
class Foo(object):
def __init__(self, func):
self._func = func
def __call__(self):
print ('class decorator runing')
self._func()
print ('class decorator ending')
@Foo
def bar():
print ('bar')
bar()