Python中如何实现 a.xxx 返回 a 本身?
我想要实现一个功能,有 class A,a = A(),a == None 返回 True,同时 a.xxx (其中 xxx 可以随表写)返回 a 本身。
下面说说我的目的,我经常有这样的代码:
if a and a.b and a.b.c and a.b.c.d:
# do something
我觉得这样写太丑了,所以希望可以直接写成:
if a.b.c.d:
# do something
目前我写了一个代码,如下:
运行此代码时抛出异常:
Traceback (most recent call last):
File “test.py”, line 19, in <module>
print a.sdjl
RuntimeError: maximum recursion depth exceeded
Python中如何实现 a.xxx 返回 a 本身?
前 20 个回复必感谢!
class SelfReturner:
def __getattr__(self, name):
# 无论访问什么属性都返回实例本身
return self
# 使用示例
a = SelfReturner()
print(a is a.xxx) # True
print(a is a.xxx.yyy.zzz) # True
print(a.xxx == a) # True
# 实际应用场景:链式调用
class Chainable:
def __init__(self, value=0):
self.value = value
def __getattr__(self, name):
# 这里可以记录方法调用,然后返回self实现链式调用
def method(*args, **kwargs):
print(f"调用方法: {name}{args}")
return self
return method
def get_value(self):
return self.value
c = Chainable()
result = c.add(5).subtract(3).multiply(2)
print(result.get_value()) # 0,因为方法只是打印,没有实际修改值
核心原理是重写 __getattr__ 魔法方法。当访问对象不存在的属性时,Python会调用这个方法。我们让它始终返回 self,就能实现 a.xxx 返回 a 本身。
这种模式在构建DSL(领域特定语言)或链式API时很有用,比如一些测试框架的断言链。不过要注意,这会覆盖所有不存在的属性访问,可能影响正常属性错误提示。
简单说就是重写 __getattr__ 返回 self。
你直接把代码块 a.b.c.d try 一下不就行了。
kotlin 倒是有处理你这种问题的解决方法,Python 我还没见过。。
那不是一样丑么
没看懂什么需求, a 必定不为 None 啊,或者只要__getattr__
<br>>>> class A(object):<br>... <br>... def xxx(self):<br>... return self<br>... <br>>>> a = A()<br>>>> a<br><__main__.A object at 0x10e8809d0><br>>>> <a target="_blank" href="http://a.xxx" rel="nofollow noopener">a.xxx</a><br><__main__.A object at 0x10e8809d0><br>
我这样回复你也感谢?
try 最省事,最明白
if xxx(a,‘a.b.c.d’): pass
<br>def hasattrs(obj, attrs):<br> attrs = attrs.split('.')<br> objs = attrs[0]<br> for attr in attrs[1:]:<br> if hasattr(obj, attr):<br> obj = eval('{}.{}'.format(objs, attr))<br> objs += '.{}'.format(attr)<br> else:<br> return False<br> return obj<br><br>class C():<br> d = 233<br><br><br>class B():<br> c = C()<br><br><br>class A():<br> b = B()<br><br><br>a = A()<br>print(hasattrs(a, 'a.b.c.d'))<br>print(hasattrs(a, 'a.b.e.d'))<br>
大概这样
好问题,这个语法类似于 C# null-conditional operator https://msdn.microsoft.com/en-us/magazine/dn802602.aspx
if a?.b?.c?.d:
PEP 505 提出过这个想法 https://www.python.org/dev/peps/pep-0505/
如果你只是想要 class A 下面一层的话,那就是 getattr
但如果你想要语法层面的东西的话,还是一串 and 吧
第一次见到这么奇怪的需求。。。这个有什么用吗?
很有用,举个例子,假设有表 A,其中有一个字段名为 Bid,这个字段保存了表 B 的主键,用某种方法得到表 A 的某个数据 a 后,就可以用 a.b 直接得到表 B 的数据(其中 b 的 id 等于 a.Bid )
同理,可以 a.b.c.d 这样得到多个表的关联数据,例如:product.shop.mall.address
我的程序中大量使用了这样的代码,这样我就不用去操作数据库了,例如我有列表 products,现在需要得每个商品的商家列表,可以这样写:
shops = [p.shop fpr p in products]
注意,p.shop 这一步其实自动查询的表 Shop,如果我不调用 p.shop,就没有查表操作
这样,如果我有一个 product,我需要判断这个商品所在商家所在商场是否有地址信息,我就可以直接写成:
if product.shop.mall.address:
# do something
如果在其中某一步发现数据不存在,例如 shop 其实不存在,那么 shop 得到的其实就是我问题中提出的 class A 的实例 a。
此时 product.shop == None,且同时 product.shop.mall.address == product.shop.mall == producj.shop == None
前排帮顶 蹭个感谢
直接用,try 一下就行了。 改函数的话更麻烦,要使用异常检查的机制啊。
二楼正解
>>> class A:
… def getattr(self, key):
… return self
… def repr(self):
… return ‘None’
…
这个有需求很像 django 里的 qureyset,可以借鉴下 django 的源码
PS: 更合理的做法是
>>> class A:
… def getattr(self, key):
… if (key.startswith(’_’)):
… raise AttributeError
… return self
你有没有想过,a.anything 都返回 a 的话,你就拿不到 a 上任何东西了…
比如 product.shop 返回 product,那么 product.shop.mall 也返回 product,product.shop.mall.address 也返回 product,这…
他的意思是制造一个 blackhole 来使得 none.xxx 不崩溃且 blackhole==none 成立
你这是在挖坑啊,到处是 N+1 查询,按你的描述 product.shop.mall.address 就要查 2 次数据库,多写几行就几十次了
描述器看看?
非常感谢,此方法可行! 能解释一下为什么这样可以么?
宁可多费机器一分,不费程序员一秒,体育老师没教过么~
你 print 的时候,python 会尝试把 object 搞成字符串,这会导致 python 尝试调用__repr__或者__str__
正常的 class A 会导致 AttributeError,于是 python 就知道不能这么操作。
你的 class A 则是这样的
a.repr = a.str = a.call = a
于是,首先 python 获得 a.repr,然后尝试调用 a.repr(a),因为 a 不是函数,但是 a.__call__也就是 a.repr.__call__存在,所以会尝试执行 a.repr.call(),因为 a.repr.call = a.call = a, 所以 a.repr.call()又会去找 a.repr.call.__call__然后执行它……
于是就无限递归啦
明白了,非常感谢!

