__new__、__getitem__()、__call__()

__new __

当使用“类名([实参])”创建实例对象时,Python解释器的主要处理过程包括两大步:
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
class Parent(object):
	def __new__(cls, *args, **kwargs):
		print("父类的__new__()被调用,其形参cls对应实参的id:",id(cls))  
		#cls接收的是子类child
		obj = super().__new__(cls)
		print("创建的实例对象的id:",id(obj))
		return obj

class Child(Parent):
	def __init__(self,name):
		print("子类的__init__()被调用,其形参self对应实参的id:",id(self))
		self.name = name

child = Child("Mike")

#父类的__new__()被调用,其形参cls对应实参的id: 1651288223736
#创建的实例对象的id: 1651308602704
#子类的__init__()被调用,其形参self对应实参的id: 1651308602704

print("父类Parent的id:",id(Parent))
print("子类Child的id:",id(Child))
print("创建对象的id:",id(child))

#父类Parent的id: 1651288235064
#子类Child的id: 1651288223736
#创建对象的id: 1651308602704

__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]

__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

__doc __()

调用内置函数dir得到的类对象的所有属性中,有一个特殊属性叫__doc__,用于表示类对象的文档字符串。
一、什么是类对象的文档字符串(docstring)
与函数的文档字符串类似,位于类对象的第一行的字符串被称为类对象的文档字符串,通常用三个引号表示。类对象的文档字符串是对类对象的功能的简要描述。
二、访问类对象的文档字符串
通过类对象的特殊属性__doc__可以访问类对象的文档字符串。
调用内置函数help()得到的帮助信息中会包含类对象的文档字符串。

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

class MyClass(object):
	ca = "ca"
	def __init__(self_:
		self.ia = "ia

__slots __

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

class MyClass(object):
	__slots__ = ("attr1","do_sth1")
mc = MyClass()

mc.attr1 = 18
print(mc.attr1)   #18

默认情况下,访问实例对象的属性时通过访问该实例对象的特殊属性__dict__来实现的。
例如:访问obj.x其实访问的是obj.dict[‘x’]
在类对象中定义了特殊属性__slots__后,其实例对象就不会再创建特殊属性__dict__了,而是为每个属性创建一个描述器,访问属性时就会直接调用这个描述器。调用描述器比访问__dict__要快。因此,在类对象中定义特殊属性__slots__可以提高属性的访问速度。此外,在类对象中定义了特殊属性__slots__后,由于其实例对象不再创造特殊属性__dict__,同时特殊属性__dict__是一个字典,字典的本质是哈希表,是一种用空间换取时间的数据结构。因此,在类对象中定义特殊属性__slots__可以减少内存消耗。 ·
如果子类也定义了特殊属性__slots__,那么子类的实例对象可以动态绑定的属性和方法的名称为子类的__slots__加上父类的__slots__。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值