荣誉感和责任感这东西固然重要,不过只是对于英雄人物而言,星际争霸里的小狗素来无需荣誉感和责任感。
类属性和实例属性查找顺序
属性:在内部定义的方法或者变量
使用代码:
class magic:
a = 'langzi'
def __init__(self,x):
self.x = x
# 这里传入的x已经属于这个对象
def run(self):
return self.x
m = magic('xx')
m.a = 'LANGZILANGZI'
print(m.a)
# 查找实例的属性
print(magic.a)
# 查找类的属性
print(m.x)
# 查找实例的属性
返回结果:
'LANGZILANGZI'
'langzi'
'xx'
查找顺序是由下而上的查找顺序,init是初始化实例的属性,要记住这里使用magic.x是会报错的,因为init是初始化实例,这个实例成为m,并不在属于magic。
可能这样举例子不清晰,重新再看看代码
class magic:
name = '浪子'
def __init__(self,name):
self.name = name
m = magic('langzi')
print(m.name)
print(magic.name)
返回结果:
langzi
浪子
这样是不是就比较清晰了,类中的name=’浪子’是属于magic类当中的,实例m.name是属于实例m当中的,是在类中init初始化的属性。
他们的查找顺序是这样:
- 找m.name的时候,由下而上,会先找到m。
- 找到m的初始话对象,从init开始查找,就会找到初始化传入的name
- 如果init中没有name的话,就会往上走,查找类中是不是存在name
就好像这样的代码:
class magic:
# def __init__(self,name):
# self.name = name
name = '浪子'
m = magic()
print(m.name)
print(magic.name)
返回结果:
浪子
浪子
三大方法
python类的调用有三大方法,分别是类方法,静态方法,实例方法。这三个方法在曾经的文章有说过。Python面向对象编程
这里就不多做代码重写,去原链接查看学习即可。
数据封装与私有属性
私有属性,也叫私有方法,是以双下划线开头的命名变量。
无法通过实例方法和子类来调用的,只能通过类中写的方法来调用。
比如:
class magic:
__user = '浪子'
a = magic
print(magic.__user)
print(a.__user)
加了双下划线的user就是私有属性,是没法通过下面两种方式进行调用的,唯一可以调用这个私有属性的方法就是使用类方法。
class magic:
__user = '浪子'
@classmethod
def run(cls):
print(cls.__user)
magic.run()
只有这样才能调用类的私有属性,这也就是对数据做了一个很好的封装。
但是这样的封装并不是完全安全的,比如你看下面的代码:
class magic:
__user = '浪子'
m = magic
print(m._magic__user)
这样能直接调用user,说白了这是一个小技巧python把私有变量偷偷隐藏起来变成了这样子。
python的自省机制
自省:通过一定的机制,查询到对象的内部结构
使用__dict__方法查询类的属性:
class magic:
'我是注释'
user = '浪子'
def run(age):
print(age)
for x,y in magic.__dict__.items():
print(x,':',y)
返回结果:
__module__ : __main__
__doc__ : 我是注释
user : 浪子
run : <function magic.run at 0x0000018AB312CC80>
__dict__ : <attribute '__dict__' of 'magic' objects>
__weakref__ : <attribute '__weakref__' of 'magic' objects>
通过dict来获取类的内部结果,记住通过magic.__dict__[‘user’]=’小桃红’也可以动态操作属性。
不仅仅是dict,通过dir可以更加强大的列出该类的所有属性。
super函数
super函数,调用父类。在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用 super 来实现。
class A:
def __init__(self,name):
self.name = name
def run(self):
print(self.name+'6666666')
class B(A):
def __init__(self,name):
self.name = name
def run(self):
print(self.name+'7777777')
super().run()
#这里是调用父类的run()方法
# 还可以这样super().__init__(name=name)这样的格式
c = B('浪子')
c.run()
返回对象:
浪子7777777
浪子6666666
事实上,super 和父类没有实质性的关联,super(cls, inst) 获得的是 cls 在 inst 的 MRO 列表中的下一个类。MRO则是python中类继承关系选择的一种,有点像是广度优先原则,可以print m.__mro__查看。