深入类与对象-中

荣誉感和责任感这东西固然重要,不过只是对于英雄人物而言,星际争霸里的小狗素来无需荣誉感和责任感。

类属性和实例属性查找顺序

属性:在内部定义的方法或者变量

使用代码:

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初始化的属性。

他们的查找顺序是这样:

  1. 找m.name的时候,由下而上,会先找到m。
  2. 找到m的初始话对象,从init开始查找,就会找到初始化传入的name
  3. 如果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__查看。

坚持原创技术分享,您的支持将鼓励我继续创作!
------ 本文结束 ------

版权声明

LangZi_Blog's by Jy Xie is licensed under a Creative Commons BY-NC-ND 4.0 International License
由浪子LangZi创作并维护的Langzi_Blog's博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证
本文首发于Langzi_Blog's 博客( http://langzi.fun ),版权所有,侵权必究。

0%