python类进阶20160707

继承

instance.class #查看实例所属的类
在子类中可以重写父类的方法(名称相同),那么在子类里,父类原来的方法被覆盖就无效了。
如果在子类中重写__init__(self),想要继承父类的___init__怎么办? 两种方法:

  1. father_class.__init__(self,属性)
class son_class(father_class):
    def __init__(self,teacher,web):#web为父类参数
    self.teacher = teacher
    father_class.__init__(self,web) #unbound menthod!
    
  1. super函数
class son_class(father_class):
     def __init__(self,teacher,web):#web为父类参数
    self.teacher = teacher
    super(son_class,self).__init__(web)
#查看继承顺序 
类名.__mro__
#查看类的属
类名.__dict__

继承顺序是广度优先,即先搜索上一层的所有父类,然后再从头开始搜索父类的父类,DBS。

方法

绑定方法与非绑定方法

class foo():
    def bar(self):
        print('normal class')

>>> f = foo()
>>> f.bar()
normal class
>>> foo.bar()
Traceback (most recent call last):
  File "", line 1, in 
    foo.bar()
TypeError: bar() missing 1 required positional argument: 'self'
>>> foo.bar(f)
normal class

foo.bar()是一个非绑定方法;f.bar()是一个绑定方法;
实例

>>> foo.bar

>>> f.bar
>
>>> 
>>> foo.__dict__
mappingproxy({'__dict__': , '__weakref__': , '__doc__': None, 'bar': , '__module__': '__main__'})
>>> foo.__dict__['bar']

>>> foo.__dict__['bar']()
Traceback (most recent call last):
  File "", line 1, in 
    foo.__dict__['bar']()
TypeError: bar() missing 1 required positional argument: 'self'
>>> foo.__dict__['bar'](f)
normal class
>>> foo.__dict__['bar'].__get__(None,foo)

>>> foo.__dict__['bar'].__get__(f,foo)
>

小结一下:

  1. dict’方法返回类的所有属性和方法,并且是个字典,可以调用
  2. get’方法能够调用类方法,在参数为None时(类本身)为非绑定方法,参数为实例时,为绑定方法
  3. 总之,类调用方法,就是非绑定方法(注意要加进去实例参数);实例调用方法,就是绑定方法(实例隐式传入)。

类方法与静态方法

类方法
class foo(object):
    one = 0
    def __init__(self):
        foo.one = foo.one + 1

    @classmethod
    def bar(cls):
        return cls.one

if __name__ == '__main__':
    f1 = foo()
    print(foo.one)
    f2 = foo()
    print(foo.one)

    print(f1.bar())
    print(f1.one)
    print(foo.bar())

    print('*'*10)
    f1.one = 8
    foo.one = 9
    print(f1.one)
    print(f1.bar())
    print(foo.bar())
>>> 
1
2
2
2
2
**********
8
9
9
>>> 

我们发现无论是用实例还是类来调用加了装饰器@classmethod的函数bar(),都是返回类的属性;而且我们发现类属性可以和实例的类属性不同(这是什么鬼啊)。类方法的目的在于把类传进来而不用把函数写在外面。

静态方法

@staticmethond这种方法跟在类外定义一个普通函数相同(只是把类外函数写进来了而已),但是在调用的时候要用self.func()来调用。

t = 0
class foo():
    def __init__(self,name):
        self.name = name

    @staticmethod
    def bar():
        t = 99
        return t

    def get_name(self):
        if self.bar():
            return self.name
        else:
            return 'no person'

if __name__ == "__main__":

    f = foo('cangjingkong')
    name = f.get_name()
    print(name)
>>> 
cangjingkong
>>> 

其实很无聊感觉。

两种方法的比较与总结

其实,感觉都差不多@classmethod是为了把类外使用类作为参数的函数写进来,参数为cls(类,但是你可以随意命名)而且无论是绑定方法还是非绑定方法调用(可耻地用了术语),都返回的是类属性,而不是实例的类的属性(好拗口);@staticmethod是为了把类外的函数写进来,参数像在类外写函数一样,没有self,但是在类内调用的时候要用self。

以上。

你可能感兴趣的:(python类进阶20160707)