关于python中的钩子方法和内置函数的举例

在学习python的类知识的时候,总是看到各种带__的属性、方法,其中上次也总结了这些带下划线的成员的知识点。这里面有一些我感到特别的好奇,所以也做一下总结。

__getattr__getattr

我首先感到好奇的类当中的反射。在一个定义的类当中,可以用getattr(object, name, [,defalut])来获取object对象中的name属性,同时也有的使用object.__getattr__(self, name)来获取objectname属性。

这两个长得那么像,总感觉他们是一个东西啊。于是我开始进一步去了解后,发现实际上他们两个,还真不是一个东西。getattrpython自带的全局函数,而__getattr__是一个需要用户在类中定义以后才可以用的方法。这里就需要搞清楚python自带的全局函数和这种需要用户在类中自定义的方法的区别是什么?

python自带的全局函数是python自带的,随时所有人都可以用,在哪里都可以用;而需要用户在类中定义的方法(也叫钩子方法)则是用户定义了就有,没定义就按python默认的走,有点类似用户定义了,解释器就会在适当的时机下去触发它。所以他们本质上是不一样的。

getattr__getattr__来举例:

python 复制代码
class A:
	pass
	
class B:
	def __getattr__(self, name):
		print(f'正在访问{self.name}')
		return self.name

a = A()
b = B()

print(a.x)    
# -> AttributeError: 'A' object has no attribute 'x'
# class A没有定义__getattr__钩子方法,所有解释器就会抛出异常

print(b.x)    
# -> 正在访问x
# -> x
# class B定义了__getattr__钩子方法,所有这里解释器就去触发了钩子方法,返回了x  

print(getattr(a, 'x', 'default a'))
# -> default a

print(getattr(a, 'x'))
# -> AttributeError: 'A' object has no attribute 'x'

print(getattr(b, 'x', 'default b'))
# -> 正在访问x
# -> x

# 这里就体现了getattr和__getattr__的联系,下面用一个图来体现他们俩的联系

getattr__getattr__的联系:

也不是所有的钩子函数都类似__getattr__getattr它俩这样的关系,比如len()__len__它们俩就与之不一样。len()也是python内置内置的全局函数,但它需要在类中定义了__len__才可以使用,平常我们使用len(1)len([1,2,3])可以用,是因为在int类、str类、list类中已经定义了__len__方法了。

python 复制代码
class A:
	pass

class B:
	def __len__(self):
		return 42
		
class C:
	def __len__(self):
		return "42"
		
a = A()
b = B()
c = C()

len(a)
# --> TypeError: object of type 'A' has no len()
# 虽然len是内置函数,但是它是去调用__len__这个钩子方法,如果用户定义了这个钩子方法,这个len才可以正常使用,没定义,就不能正常使用
# 这个和getattr这个内置函数就有一些区别
# getattr内置函数是,不管定义还是没定义,都可以使用,只是如果定义了__getattr__这个钩子方法,getattr会多调用一步

print(len(b))
# --> 42

print(len(c))
# --> TypeError: 'str' object cannot be interpreted as an integer
# 注意这里报错,是因为内置函数len要求__len__必须返回非负整数,而自己定义的__len__返回了一个字符串,所以报错

从上面两个例子来看,内置函数和钩子方法有点像是python的制造大师们,把内置函数开发好了,提供给开发者们用,但是也配置了一些使用方法,有的内置函数使用方法上要配合一些钩子函数来使用,而这个内置函数对钩子函数的使用方式又各有不同。

__getattr____getattribute__

除了有内置函数getattr__getattr__很像以外,还有另外一个方法__getattribute__也和它非常像,那它们俩又是什么关系呢?他们俩都是python中的魔术方法,但__getattr__是用户定义了才有,而__getattribute__是在python的基类object类中定义好的,不管用户定义还是不定义,它都存在,只是如果用户定义了,就会覆盖__getattribute__。所以如果说钩子方法是用户定义才有,没定义就没有的话,__getattribute__就不算是一个钩子方法了。

那么他们俩在功能上有什么联系?我也用一个图来进行总结。这个图中访问类中的属性,可以是通过object.xxx的形式来访问,也可以是通过getattr(object,'x',)的方式来访问。

注意 :如果getattr中提供了默认值,那么在调用__getattribte__以后如果没有返回值,那么就直接去getattr的默认值了,不会再去调用__getattr__了。

相关推荐
动能小子ohhh2 小时前
AI智能体(Agent)大模型入门【2】--基于llamaindx部署本地的聊天模型。
人工智能·python·aigc·ai编程
MediaTea2 小时前
Python 第三方库:SymPy(符号计算工具)
开发语言·python·数学建模
Goona_2 小时前
PyQt数字转大写金额GUI工具开发及财务规范实现
python·小程序·交互·pyqt
Pocker_Spades_A3 小时前
Python快速入门专业版(二十二):if语句进阶:嵌套if与条件表达式(简洁写法技巧)
开发语言·python
看海的四叔3 小时前
【Python】Python解决阿里云DataWorks导出数据1万条限制的问题
开发语言·python·阿里云·dataworks·maxcomputer
吾日三省吾码3 小时前
用 Python UTCP 直调 HTTP、CLI、MCP……
开发语言·python·http
深耕AI3 小时前
【参数详解与使用指南】PyTorch MNIST数据集加载
人工智能·pytorch·python
站大爷IP3 小时前
PID控制算法原理与Python实现:从理论到实践的通俗解析
python
aopstudio3 小时前
如何优雅地清理Hugging Face缓存到本地的模型文件(2025最新版)
人工智能·python·缓存·语言模型