gpt4 book ai didi

python - 如何使用 "open up"3rd 方库基于 __slots__ 的对象实例进行属性分配?

转载 作者:行者123 更新时间:2023-12-01 02:48:27 26 4
gpt4 key购买 nike

假设我想为使用槽返回实例的第三方库返回的对象实例分配新属性。

(例如,在 SQLAlchemy 的 RowProxy 行上为您不打算写回数据库的数据设置一些值。)

因为实例有__slots__,所以我将得到一个AttributeError或类似的错误。这是预期的结果,但是解决方法是什么?

期望的行为/约束

  1. 认为第 3 方库是一个黑匣子,无法更改其返回类型。
  2. 尽可能多地保留原始实例的行为(方法、属性等)。
  3. 分配给槽中的属性应该会影响原始实例的属性。

这就是我的想法,Proxy2 可以工作,但是有没有更优雅/更简单的东西?它破裂有什么风险?它可以在 Python 3 上运行吗(我使用的是 2.7,但计划最终升级到 3.x)。

class Slotted(object):
__slots__ = ("a","b")

def hello(self):
print("hello %s" % (self.a))

def __init__(self, a="1", b="2"):
self.a = a
self.b = b

def test_it(f):

fname = f.__name__

print("\n\ntest_it(%s)" % (fname))

instances = [Slotted(a=11), Slotted()]
try:
li_test = [f(obj) for obj in instances]
except Exception, e:
print("%s.failure at instance modification:%s" % (fname, str(e)[0:100]))
return

for cntr, tgt in enumerate(li_test):
try:
tgt.cntr = cntr
print("tgt.cntr:%s" % (tgt.cntr))
#do I still have my function?
tgt.hello()
tgt.a = 100
except Exception, e:
print("%s.failure:%s" % (fname, str(e)[0:100]))
return

#test that an attribute assignment to the slots actually went there...
for ori in instances:
try:
assert ori.a == 100
except AssertionError:
print("%s.failure:original instance should have its slot-based attribute set to 100, but is still %s" % (fname, ori.a))
break

print "%s.success" % (fname)

class Proxy2(object):
"""this works, can it be improved on?"""

def __init__(self, obj):
self.__dict__["_obj"] = obj

def __setattr__(self, attrname, value):
if attrname in self._obj.__slots__:
setattr(self._obj, attrname, value)
else:
self.__dict__[attrname] = value

def __getattr__(self, attrname):
try:
return getattr(self._obj, attrname)
except AttributeError:
raise

#subclass Slotted
class Opener(Slotted):
"""fails w Slotted' object layout differs from 'Opener'"""
pass

class Opener2(Slotted):
"""fails w Slotted' object layout differs from 'Opener2'"""
__slots__ = Slotted.__slots__ + ("__dict__",)

#functions to modify the original instances
def proxy_instances(obj):
#this works
return Proxy2(obj)

def do_nothing(obj):
#fails, normal, this is the baseline slots behavior
return obj

def modify_class(obj):
#change the instance's class to a subclass that has a __dict__
obj.__class__ = Opener

def modify_class2(obj):
#change the instance's class to a subclass to add __dict__ to the __slots__
obj.__class__ = Opener2

for func in [do_nothing, modify_class, modify_class2, proxy_instances]:
test_it(func)

输出:

test_it(do_nothing)
do_nothing.failure:'Slotted' object has no attribute 'cntr'


test_it(modify_class)
modify_class.failure at instance modification:__class__ assignment: 'Slotted' object layout differs from 'Opener'


test_it(modify_class2)
modify_class2.failure at instance modification:__class__ assignment: 'Slotted' object layout differs from 'Opener2'


test_it(proxy_instances)
tgt.cntr:0
hello 11
tgt.cntr:1
hello 1
proxy_instances.success

最佳答案

我会获取从第 3 方库返回的结果,并将其与我想要存储的其他数据一起存储在我自己的某种容器对象(例如类或字典)中。

这种方法会更加明确、直接、易于理解、不那么棘手。由于它不是以一种棘手的方式对第三方数据进行猴子修补,因此更有可能避免神秘的错误。

关于python - 如何使用 "open up"3rd 方库基于 __slots__ 的对象实例进行属性分配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45068365/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com