特殊属性 | 含义 | 示例 |
__base__ | 类的基类 |
|
__bases__ | 类的基类元组 | |
__mro__ | 显示方法查找顺序,基类的元组 | |
mro() | 同上 | int.mro() |
__subclasses__() | 类的子类列表 | int.__subclasses__() |
class Animal: __COUNT = 100 HEIGHT = 0 def __init__(self,age,weight,height): self.__COUNT += 1 self.age = age self.__weight = weight self.HEIGHT = height def eat(self): print("{} eat".format(self.__class__.__name__)) def __getweight(self): print(self.__weight) @classmethod def showcount1(cls): print(cls.__COUNT) @classmethod def __showcount2(cls): print(cls.__COUNT) def showcount3(self): print(self.__COUNT) class Cat(Animal): NAME = "CAT" __COUNT = 200 #a = Cat() # TypeError: __init__() missing 3 required positional arguments: 'age', 'weight', and 'height' a = Cat(30,50,15) a.eat() # Cat eat print(a.HEIGHT) # 15 #print(a.__COUNT) # AttributeError: 'Cat' object has no attribute '__COUNT' #print(a.__showcount2) # AttributeError: 'Cat' object has no attribute '__showcount2' #print(a.__getweight) # AttributeError: 'Cat' object has no attribute '__getweight' a.showcount3() # 101 a.showcount1() # 100 print(a.NAME) # CAT print(Animal.__dict__) # {'__module__': '__main__', '_Animal__COUNT': 100, 'HEIGHT': 0, '__init__': function Animal.__init__ at 0x020DC228>, 'eat': function Animal.eat at 0x020DC468>, '_Animal__getweight': function Animal.__getweight at 0x02126150>, 'showcount1': classmethod object at 0x020E1BD0>, '_Animal__showcount2': classmethod object at 0x020E1890>, 'showcount3': function Animal.showcount3 at 0x021264F8>, '__dict__': attribute '__dict__' of 'Animal' objects>, '__weakref__': attribute '__weakref__' of 'Animal' objects>, '__doc__': None} print(Cat.__dict__) # {'__module__': '__main__', 'NAME': 'CAT', '_Cat__COUNT': 200, '__doc__': None} print(a.__dict__) # {'_Animal__COUNT': 101, 'age': 30, '_Animal__weight': 50, 'HEIGHT': 15}
从父类继承、自己没有的,就可以到父类中找
私有的都是不可访问的,但是本质上依然是改了名称放在这个属性所在的类的了【__dict__】中,知道这个新民成就可以了直接找到这个隐藏的变量,这是个黑魔法慎用
总结
属性查找顺序:实例的【__dict__】------类的【__dict__】-----父类【__dict__】
如果搜索这些地方后没有找到异常,先找到就立即返回
class Animal: def shout(self): print("Animal shouts") class Cat(Animal): def shout(self): print("miao") a = Animal() a.shout() # Animal shouts b = Cat() b.shout() # miao print(a.__dict__) # {} print(b.__dict__) # {} print(Animal.__dict__) # {'__module__': '__main__', 'shout': function Animal.shout at 0x017BC228>, '__dict__': attribute '__dict__' of 'Animal' objects>, '__weakref__': attribute '__weakref__' of 'Animal' objects>, '__doc__': None}
Cat类中shout为什么没有打印Animal中shout的方法,方法被覆盖了?
那子类如何打印父类的同命的方法
class Animal: def shout(self): print("Animal shouts") class Cat(Animal): def shout(self): print("miao") def shout(self): print("super(): " , super()) print(super(Cat, self)) super().shout() super(Cat,self).shout() # 等价于super().shout() self.__class__.__base__.shout(self) #不推荐使用 a = Animal() a.shout() # Animal shouts b = Cat() b.shout() # super(): super: class 'Cat'>, Cat object>> # super: class 'Cat'>, Cat object>> # Animal shouts # Animal shouts # Animal shouts print(a.__dict__) # {} print(b.__dict__) # {} print(Animal.__dict__) # {'__module__': '__main__', 'shout': function Animal.shout at 0x019AC228>, '__dict__': attribute '__dict__' of 'Animal' objects>, '__weakref__': attribute '__weakref__' of 'Animal' objects>, '__doc__': None} print(Cat.__dict__) # {'__module__': '__main__', 'shout': function Cat.shout at 0x019F6150>, '__doc__': None}
super(Cat,self).shout()的作用相当于
那对于类方法和静态方法是否也同样适用尼?
class Animal: @classmethod def class_method(cls): print("class_method") @staticmethod def static_method(): print("static_methond_animal") class Cat(Animal): @classmethod def class_method(cls): super().class_method() # class_method print("class_method_cat") @staticmethod def static_method(cls,self): super(Cat,self).static_method() print("static_method_cat") b = Cat() b.class_method() # class_method # class_method_cat b.static_method(Cat,b) # static_methond_animal # static_method_cat
这些方法都可以覆盖,原理都一样,属性字典的搜索顺序
看以下一段代码,有没有问题
class A: def __init__(self,a): self.a = a class B(A): def __init__(self,b,c): self.b = b self.c = c def printv(self): print(self.b) print(self.a) a = B(100,300) print(a.__dict__) # {'b': 100, 'c': 300} print(a.__class__.__bases__) # (class '__main__.A'>,) a.printv() # 100 # AttributeError: 'B' object has no attribute 'a'
上例代码
class A: def __init__(self,a): self.a = a class B(A): def __init__(self,b,c): super().__init__(b+c) # A.__init__(self,b+c) self.b = b self.c = c def printv(self): print(self.b) print(self.a) a = B(100,300) print(a.__dict__) # {'a': 400, 'b': 100, 'c': 300} print(a.__class__.__bases__) # (class '__main__.A'>,) a.printv() # 100 # 400
作为好的习惯,如果父类定义了__init__方法,你就改在子类__init__中调用它【建议适用super()方法调用】
那子类什么时候自动调用父类的【__init__】方法?
例子一:【B实例的初始化会自动调用基类A的__init__方法】
class A: def __init__(self): self.a1 = "a1" self.__a2 = "a2" print("A init") class B(A): pass b = B() # A init print(b.__dict__) # {'a1': 'a1', '_A__a2': 'a2'}
例子二:【B实例的初始化__init__方法不会自动调用父类的初始化__init__方法,需要手动调用】
class A: def __init__(self): self.a1 = "a1" self.__a2 = "a2" print("A init") class B(A): def __init__(self): self.b1 = "b1" self.__b2 = "b2" print("b init") #A.__init__(self) b = B() # b init print(b.__dict__) # {'b1': 'b1', '_B__b2': 'b2'}
那如何正确实例化?
class Animal: def __init__(self,age): print("Animal init") self.age = age def show(self): print(self.age) class Cat(Animal): def __init__(self,age,weight): #调用父类的__init__方法的顺序 决定show方法的结果 super(Cat, self).__init__(age) print("Cat init") self.age = age + 1 self.weight = weight a = Cat(10,5) a.show() # Animal init # Cat init # 11
怎么直接将上例中所有的实例属性改变为私有属性?
class Animal: def __init__(self,age): print("Animal init") self.__age = age def show(self): print(self.__age) class Cat(Animal): def __init__(self,age,weight): #调用父类的__init__方法的顺序 决定show方法的结果 super(Cat, self).__init__(age) print("Cat init") self.__age = age + 1 self.__weight = weight def show(self): print(self.__age) a = Cat(10,5) a.show() # Animal init # Cat init # 11 print(a.__dict__) # {'_Animal__age': 10, '_Cat__age': 11, '_Cat__weight': 5}
到此这篇关于浅谈Python类的单继承相关知识的文章就介绍到这了,更多相关Python类的单继承内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!