面向对象编程(第五篇)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/dongzixian/article/details/90756567

__new__

1.调用特殊方法__new__()创建实例对象
查找该类对象是否实现了特殊方法__new__(),如果没有实现,则去其父类中依次查找,直到类对象object
2.调用特殊方法__init__()对创建的实例对象进行初始化
__new__()返回的实例对象会作为实参数被自动传递给__init__()的第一个形参self
class Parent(object):
    def __new__(cls,*args,**kwargs):
        pass
class Child(Parent):
    def __init__(self,name):
        pass
id(Parent)
>2596561457880
id(Child)
>2596561481480
class Parent(object):
    def __new__(cls,*args,**kwargs):
        print("父类的__new__()被调用,其形参cls对应实参的id",id(cls))
        obj = super().__new__(cls)
        print("创建的实例对象的id",id(obj))
        return obj
class Child(Parent):
    def __init__(self,name):
         print("子类的__new__()被调用,其形参cls对应实参的id",id(self))
         self.name = name
子类实例化,子类把地址传给父类,父类运作,父类再把地址传给子类
child = Child("Mike")
>父类的__new__()被调用,其形参cls对应实参的id 2596561451272
创建的实例对象的id 2596568411608
子类的__new__()被调用,其形参cls对应实参的id 2596568411608
print("父类Parent的id:",id(Parent))
print("子类Child的id:",id(Child))
print("创建的实例对象的id:",id(child))
>父类Parent的id: 2596561482424
子类Child的id: 2596561451272
创建的实例对象的id: 2596568411608

__getitem__(),__setitem__(),__delitem__()

如果想让自定义类对象的实例对象可以像列表和字典那样,使用中括号语法来操作数据
1.getitem(self,key)
当执行操作obj[key]时,会自动调用该特殊方法
2.setitem(self,key,value)
当执行操作obj[key] = value时,会自动调用该特殊方法
3.delitem(self,key)
当执行操作del obj[key]时,会自动调用该特殊方法
class MyDict(object):
    def __init__(self):
        self.data = {}
    def __getitem__(self,key):
        return self.data[key]
    def __setitem__(self,key ,value):
        self.data[key] = value
    def __delitem__(self,key):
        del self.data[key]
md = MyDict()
md["one"] = 18
md["two"] = 32
print(md.data)
>{'one': 18, 'two': 32}
删除
del md["two"] 
print(md.data)
>{'one': 18}

call()

如果在类对象中实现了特殊方法__call__(),那么就可以像调用函数一样直接调用这个类对象的实例对象,从而会自动调用特殊方法__call__()。
class MyClass(object):
    def __call__(self,*args,**kwargs):
        print(args,kwargs)
mc = MyClass()
mc()
>() {}
mc(1,2,x=3,y=4)
>(1, 2) {'x': 3, 'y': 4}
内置函数callable用于判断指定对象是否是可调用的。
除了函数对象是可调用的之外,对于实现了特殊方法__call__()的类对象,其实例对象也是可以调用的。
#内置函数
callable(print)
>True
#自定义函数
def my_fun():
      pass
print(callable(my_fun))
>True
#实现了特殊方法__call__()的类对象,其实例对象也是可以调用的。
print(callable(MyClass))
>True

__doc__

通过类对象的特殊属性__doc__可以访问类对象的文档字符串
class MyClass(object):
    """
    123
    """
    def __call__(self,*args,**kwargs):
        print(args,kwargs)
mc = MyClass()
mc()
print(MyClass.__doc__)
>   
    123
    

特殊属性__slots__

如果想要对实例对象动态绑定的属性和方法的名称进行限制,可以在其对应的类对象中定义特殊属性__slots__,并给__slots__赋值一个所有元素都为字符串的列表或元组,这样,对实例对象动态绑定的属性和方法的名称就只能来自于__slots__中的元素。
class MyClass(object):
    __slots__ = ("attrl","do_sth1")
mc = MyClass()
mc.attrl = 18
print(mc.attrl)
>18
不在名单内
mc.attr2 = 12

>---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-34-afd3ca596a00> in <module>()
----> 1 mc.attr2 = 12

AttributeError: 'MyClass' object has no attribute 'attr2'

def do_sth1(self):
    print("do_sth1被调用了")
from types import MethodType
mc.do_sth1 = MethodType(do_sth1,mc)
mc.do_sth1()
>do_sth1被调用了
不在名单内
def do_sth2():
    print("do_sth2被调用了")
mc.do_sth2 = MethodType(do_sth2,mc)

>---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-6-d60ee0e54e8c> in <module>()
      1 def do_sth2():
      2     print("do_sth2被调用了")
----> 3 mc.do_sth2 = MethodType(do_sth2,mc)

AttributeError: 'MyClass' object has no attribute 'do_sth2'

在类对象中定义特殊属性__slots__可以提高属性的访问速度
在类对象中定义特殊属性__slots__可以减少内存消耗
继承了有__slots__的父类,子类没有,则可以随意定义
继承了有__slots__的父类,子类有,则父类子类的方法属性都有

猜你喜欢

转载自blog.csdn.net/dongzixian/article/details/90756567