1
sdjl OP 前 20 个回复必感谢!
|
2
ivechan 2017-08-26 19:22:53 +08:00 1
你直接把代码块 a.b.c.d try 一下不就行了。
kotlin 倒是有处理你这种问题的解决方法,Python 我还没见过。。 |
4
xkoing 2017-08-26 19:28:34 +08:00 1
|
5
honmaple 2017-08-26 19:30:01 +08:00 1
没看懂什么需求, a 必定不为 None 啊,或者只要__getattr__
|
6
WangYanjie 2017-08-26 19:45:47 +08:00 1
|
7
cheetah 2017-08-26 19:47:49 +08:00 3
我这样回复你也感谢?
|
8
Cooky 2017-08-26 19:56:59 +08:00 via Android 1
try 最省事,最明白
|
9
zwgmlr3 2017-08-26 20:07:16 +08:00 via Android 1
if xxx(a,'a.b.c.d'): pass
|
10
zwgmlr3 2017-08-26 20:23:44 +08:00 1
```
def hasattrs(obj, attrs): attrs = attrs.split('.') objs = attrs[0] for attr in attrs[1:]: if hasattr(obj, attr): obj = eval('{}.{}'.format(objs, attr)) objs += '.{}'.format(attr) else: return False return obj class C(): d = 233 class B(): c = C() class A(): b = B() a = A() print(hasattrs(a, 'a.b.c.d')) print(hasattrs(a, 'a.b.e.d')) ``` 大概这样 |
11
zwgmlr3 2017-08-26 20:25:37 +08:00 2
|
12
hahastudio 2017-08-26 21:09:24 +08:00 2
好问题,这个语法类似于 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 吧 |
13
VShawn 2017-08-26 21:19:24 +08:00 via Android 1
第一次见到这么奇怪的需求。。。这个有什么用吗?
|
14
sdjl OP @VShawn
很有用,举个例子,假设有表 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,就没有查表操作 |
15
sdjl OP 这样,如果我有一个 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 |
16
PythonAnswer 2017-08-27 00:14:19 +08:00 via Android 1
前排帮顶 蹭个感谢
|
17
ToBeHacker 2017-08-27 00:53:36 +08:00 1
直接用,try 一下就行了。 改函数的话更麻烦,要使用异常检查的机制啊。
二楼正解 |
18
byx 2017-08-27 01:09:17 +08:00 1
|
19
yangff 2017-08-27 01:25:45 +08:00 1
>>> class A:
... def __getattr__(self, key): ... return self ... def __repr__(self): ... return 'None' ... |
20
simadad 2017-08-27 01:28:11 +08:00 via Android 1
这个有需求很像 django 里的 qureyset,可以借鉴下 django 的源码
|
21
yangff 2017-08-27 01:29:55 +08:00 1
PS: 更合理的做法是
>>> class A: ... def __getattr__(self, key): ... if (key.startswith('_')): ... raise AttributeError ... return self |
22
oott123 2017-08-27 01:32:10 +08:00 via Android
你有没有想过,a.anything 都返回 a 的话,你就拿不到 a 上任何东西了…
比如 product.shop 返回 product,那么 product.shop.mall 也返回 product,product.shop.mall.address 也返回 product,这… |
23
yangff 2017-08-27 01:34:23 +08:00 2
|
24
guyskk 2017-08-27 10:34:22 +08:00 via Android 1
你这是在挖坑啊,到处是 N+1 查询,按你的描述 product.shop.mall.address 就要查 2 次数据库,多写几行就几十次了
|
25
explist 2017-08-27 11:55:30 +08:00 1
描述器看看?
|
28
yangff 2017-08-27 15:07:25 +08:00 2
@sdjl 你 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__然后执行它…… 于是就无限递归啦 |