面向对象(四)

__new__()

当创建实例对象时,python解释器的主要处理过程分为两步:

  1. 调用特殊方法__new__()创建实例对象
    会查找该类对象中是否实现了__new__()方法,如果没有,则去父类中查找,直到类对象object
  2. 调用特殊方法__init__()对创建的实例对象进行初始化
    new()的返回实例对象会做为实参传递给__init__()的第一个参数self
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):
        print("子类的__init__()被调用,其形参self对应实参的id:",id(self))
child = Child()        

运行结果:
父类的__new__()被调用,其形参cls对应实参的id: 2599626482024
创建实例对象的id 2599651694744
子类的__init__()被调用,其形参self对应实参的id: 2599651694744

__getitem__(),__setitem__(),__delitem__()

如果想让自定义类对象的实例对象可以像列表和字典那样,使用中括号语法来操作数据,需要在类对象中实现一下特殊方法:

  1. __getitem__(self,key)
    当执行object[key]时,会自动调用该方法
  2. __setitem__(self,key)
    当执行object[key] = value时,会自动调用该方法
  3. __setitem__(self,key)
    当执行 del object[key]时,会自动调用该方法
class MyClass(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]

mc = MyClass()
mc["one"] = 18
mc["two"] = 28
mc["three"] = 38
print(mc["one"])
del mc["three"]
print(mc.data)


运行结果:
18
{'one': 18, 'two': 28}

__call__()

如果在类对象中实现了特殊方法__call__(),那么就可以像调用函数一样直接调用这个类对象的实例对象,从而会自动调用特殊方法__call__()

class MyClass(object):
    def __call__(cls,*args,**kwargs):
        print(args,kwargs)
mc = MyClass()
mc()

mc(1,2,3,one = 1,two = 2,three = 3)


运行结果:
() {}
(1, 2, 3) {'one': 1, 'two': 2, 'three': 3}

__doc__与__dict__

类对象有一个特殊的属性__doc__,用于表示类对象的文档字符串,而文档字符串是位于类对象的第一行的字符串,通常用三个引号表示,是对类对象的功能的简要概述。
通过类对象的特殊属性__doc__可以访问类对象的文档字符串。
通过内置函数help()得到的帮助信息中会包含类对象的文档字符串。

class MyClass(object):
    """这是类对象的文档字符串
    
    
    """
    pass
print(MyClass.__doc__)
help(MyClass)

运行结果:
这是类对象的文档字符串
    
    
Help on class MyClass in module __main__:

class MyClass(builtins.object)
 |  这是类对象的文档字符串
 |  
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)

对于指定的类对象和实例对象,可以访问特殊属性__dict__获得该类对象或者实例对象所绑定的所有属性和方法的字典。其中,字典中的键为属性名或者方法名。

class MyClass(object):
    age = 18
    name = "beryl"
    def __init__(self):
        self.ip = 12344
    def func(self):
        pass
    @classmethod
    def func1(cls):
        pass
    @staticmethod
    def func2():
        pass
MyClass.__dict__
mc = MyClass()
print(mc.__dict__)

运行结果:
mappingproxy({'__module__': '__main__',
              'age': 18,
              'name': 'beryl',
              '__init__': <function __main__.MyClass.__init__(self)>,
              'func': <function __main__.MyClass.func(self)>,
              'func1': <classmethod at 0x2f207edf550>,
              'func2': <staticmethod at 0x2f207edf5c0>,
              '__dict__': <attribute '__dict__' of 'MyClass' objects>,
              '__weakref__': <attribute '__weakref__' of 'MyClass' objects>,
              '__doc__': None})

{'ip': 12344}

特殊属性之__slots__

如果想要对实例对象动态绑定的属性和方法的名称进行限制,可以在其对应的类对象中定义特殊方法__slots__,并且给__slots__赋值一个所有元素都为字符串的列表或元组,这样,对实例对象动态绑定的属性和方法的名称就都只能来自于__slots__中的元素。

class MyClass(object):
    __slots__ = ("age","func1")
mc = MyClass()
mc.age = 18
def func1(self):
    print("func1被调用")
from types import MethodType
mc.func1 = MethodType(func1,mc)

print(mc.age)
mc.func1()

运行结果:
18
func1被调用
def func2(self):
    print("func2被调用")
from types import MethodType
mc.func2 = MethodType(func2,mc)

运行结果:
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-18-df2af94662ca> in <module>()
      2     print("func2被调用")
      3 from types import MethodType
----> 4 mc.func2 = MethodType(func2,mc)

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

特殊方法之__len__()

如果想让内置函数len()的实参可以是自定义类对象的实例对象,必须在自定义类对象中实现特殊方法__len__()。这样在调用内置函数len()时,在其内部会自动调用实参所对应类对象的特殊方法__len__()。

class MyClass(object):
    def __len__(self):
        return 18
print(len(MyClass()))

运行结果:
18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值