暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

python面向对象编程篇(14)-其他魔法方法补充

小儿来一壶枸杞酒泡茶 2021-03-17
358

个人其他博客地址:

简书:https://www.jianshu.com/u/d6960089b087

掘金:https://juejin.cn/user/2963939079225608

小钟同学 | 文 【原创】| QQ:308711822

  • 1:本文相关描述主要是个人的认知和见解,如有不当之处,还望各位大佬指正。
  • 2:关于文章内容,有部分内容参考自互联网,如有原创链接会声明标注;如找不到原创链接,在此声明如有侵权请联系,我会立即删除处理哟。

1  其他魔法函数补充

在python中还包含其他很多的内置的魔法方法,以下我会实践一些自己之前用到一些总结以下:我们先看看一下大概一个类的对象下大概包含哪些方法名:

查看对象的所有属性(方法)名-dir()

class A1: pass
for i in A1().__dir__():
    print(i)

输出结果为:

__module__
__dict__
__weakref__
__doc__
__repr__
__hash__
__str__
__getattribute__
__setattr__
__delattr__
__lt__
__le__
__eq__
__ne__
__gt__
__ge__
__init__
__new__
__reduce_ex__
__reduce__
__subclasshook__
__init_subclass__
__format__
__sizeof__
__dir__
__class__

1、__ module__

  • 查询当前操作的对象属于哪个模块下的。
class A1: pass
a = A1()
print(a.__module__) # 输出结果:__main__

2、__ dict__

  • 列出类或者对象中的所有成员

如类的:


class A1: pass

print(A1.__dict__) 
# 输出结果:{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'A1' objects>, '__weakref__': <attribute '__weakref__' of 'A1' objects>, '__doc__': None}



如对象的:


class A1:
    name  ="小钟同学"
    age = 56
    def __init__(self,name):
        self.name = name
print(A1("你好").__dict__)

# 输出结果:{'name': '你好'}


3、__ weakref__

  • 类和对象的弱引用属性。
class A1:
    name  ="小钟同学"
    age = 56
    def __init__(self,name):
        self.name = name
print(A1.__weakref__)
print(A1('aaa').__weakref__)
输出结果:
<attribute '__weakref__' of 'A1' objects>
None

4、__ doc__

  • 输出类的文档备注信息
class A1:
    """ 方法的描述说明 """

    def func(self):
        '''
        方法的说明222222222
        :return:
        '
''
        pass

    def func2(self):
        pass


# 打印类的说明文档
print(A1.__doc__) #  方法的描述说明 

5、__ repr__

  • 显示对象属性, 实现类到字符串的转化。通过重写方法和__str__有点类似

class A1:

    def __init__(self):
        self.name = "xiaozhong"

    def __repr__(self):
        return  "我是的名字是:"+self.name



# 显示实例对象的属性
print(A1().__repr__())

6、__ str__

--  显示对象属性, 实现类到字符串的转化。通过重写方法和__repr__有点类似

class A1:

   def __init__(self):
       self.name = "xiaozhong"

   def __repr__(self):
       return  "我是的名字是:"+self.name

   def __str__(self):
       return "我是的名字是:" + self.name

# 显示实例对象的属性
print(A1().__str__())

str 和 __ repr__的区别:

  • str:强调结果的可读性
  • repr:强调结果的准确性,常用语调式

7、__ getattribute__

  • 属性拦截器(当实例对象调用属性的时候会触发 __ getattribute__ 执行)

要点:

  • 1.getattribute(self,*args,**kwgs)中传入的参数是属性名,不是属值
  • 2.使用类名调用类属性时,不会调用__getattribute__方法,只针对实例对象对属性的调用

7.1 实例对象属性拦截示例:

class A1:

    def __init__(self):
        self.name = "xiaozhong"

    def __getattribute__(self, attr):  # 注意:attr是传入的属性名,不是属性值
        print("开始属性校验拦截功能")
        print(attr)
        return object.__getattribute__(self, attr)  # 返回属性名


# 显示实例对象的属性
print(A1().name)

输出结果为:

开始属性校验拦截功能
name
xiaozhong

7.2 实例对象属性校验重写示例:

class A1:

    def __init__(self):
        self.name = "xiaozhong"
        self.age = 23

    def __getattribute__(self, attr):  # 注意:attr是传入的属性名,不是属性值
        print("开始属性校验拦截功能")
        print(attr)
        if attr == "name":  # 注意这里引用原属性名不用self,直接引号引起来即可。
            print("现在开始调用的是name属性")
        else:
            print("现在调用的是其他属性")
        return object.__getattribute__(self, attr)  # 返回属性名



# 显示实例对象的属性
a = A1()
print(a.name)
print("========")
print(a.age)


输出结果为:

开始属性校验拦截功能
name
现在开始调用的是name属性
xiaozhong
========
开始属性校验拦截功能
age
现在调用的是其他属性
23

8、__ del__ (比较重要)

  • 析构函数,释放对象时使用,主用应用场景是解释器在进行垃圾回收时,对象的内存中被释放的时,自动触发此方法的调用。

PS:因为Python内存自动管理机制,通常我们不需要自定义此方法,而且自定义的话,搞不好有时候会无法释放,

class A1:
    def __del__(self):
        print("我被回收了!")
a = A1()
b = a
del a

输出结果为:我被回收了!

9、__ sizeof__() :

  • 给定对象的分配空间的大小(以字节为单位)
class A1:


    asdas = "sadfsdfs"

    def __init__(self):
        self.name = "xiaozhong"
        self.age = 23
        self.name2 = "xiaozhong"
print(A1().__sizeof__())



10、__ slots__  :

  • 限制实例的变量,不能动态的进行变量新增
  • 指定 __slots__属性,这样就不会再有 __dict__ 属性

加上限制后,就另一个属性就变颜色了!!!!

1 . slots定义的属性仅对当前类实例起作用,对继承了它的子类是不起作用的 2 . 如果子类需要做限制,也只能再__slots__定义,子类实例允许定义的属性就是自身的slots加上父类的slots。

class A1:


    __slots__ = ("name""age")

    def __init__(self):
        self.name = "xiaozhong"
        self.age = 23



a= A1()
print(a.name)
print(a.age)
a.age111=23 ## 这里会报错,无法动态的新增属性


子类的示例:

class A1:


    __slots__ = ("name""age")

    def __init__(self):
        self.name = "xiaozhong"
        self.age = 23

class B1(A1): pass

a= A1()
print(a.name)
print(a.age)

b= B1()
print(b.name)
b.aaaaaa = "我是子类的,我可以动态添加其他属性,不受A1父类的控制"
print(b.aaaaaa)

输出的结果:
xiaozhong
23
xiaozhong
我是子类的,我可以动态添加其他属性,不受A1父类的控制

子类也限制的示例:


class A1:


    __slots__ = ("name""age")

    def __init__(self):
        self.name = "xiaozhong"
        self.age = 23

class B1(A1):
    __slots__ = ("name2""age2")

a= A1()
print(a.name)
print(a.age)

b= B1()
print(b.name)
b.aaaaaa = "我是子类的,我可以动态添加其他属性,不受A1父类的控制"
print(b.aaaaaa)

此时会报错:
因为子类现在限制的属性有是:子类和父类的总和:
就是:__slots__ = ("name""age")+__slots__ = ("name2""age2") 只运行几个参数

输出结果:

xiaozhong
23
xiaozhong
Traceback (most recent call last):
  File "D:/code/python/local_python/AntFlask/mroro.py", line 22, in <module>
    b.aaaaaa = "我是子类的,我可以动态添加其他属性,不受A1父类的控制"
AttributeError: 'B1' object has no attribute 'aaaaaa'

参考资料:

https://zhuanlan.zhihu.com/p/61042358

https://blog.csdn.net/qq_26442553/article/details/82467777


文章转载自小儿来一壶枸杞酒泡茶,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论