我想在返回代理对象的类上创建某种描述符.索引时,代理对象检索对象的成员并将索引应用于它们.然后它返回总和.
例如,
class NDArrayProxy:
def __array__(self, dtype=None):
retval = self[:]
if dtype is not None:
return retval.astype(dtype, copy=False)
return retval
class ArraySumProxy(NDArrayProxy):
def __init__(self, arrays):
self.arrays = arrays
@property
def shape(self):
return self.arrays[0].shape
def __getitem__(self, indices):
return np.sum([a[indices]
for a in self.arrays],
axis=0)
Run Code Online (Sandbox Code Playgroud)
当我将实际数组作为成员变量时,此解决方案工作正常:
class CompartmentCluster(Cluster):
"""
Base class for cluster that manages evidence.
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.variable_evidence = ArraySumProxy([])
class BasicEvidenceTargetCluster(CompartmentCluster):
# This class variable creates a Python object named basic_in on the
# class, which implements …Run Code Online (Sandbox Code Playgroud) 为什么不能以声明方式覆盖类名,例如使用不是有效标识符的类名?
>>> class Potato:
... __name__ = 'not Potato'
...
>>> Potato.__name__ # doesn't stick
'Potato'
>>> Potato().__name__ # .. but it's in the dict
'not Potato'
Run Code Online (Sandbox Code Playgroud)
我想也许这只是在类定义块完成后被覆盖的情况.但似乎这不是真的,因为名称是可写的,但显然没有在类dict中设置:
>>> Potato.__name__ = 'no really, not Potato'
>>> Potato.__name__ # works
'no really, not Potato'
>>> Potato().__name__ # but instances resolve it somewhere else
'not Potato'
>>> Potato.__dict__
mappingproxy({'__module__': '__main__',
'__name__': 'not Potato', # <--- setattr didn't change that
'__dict__': <attribute '__dict__' of 'no really, not Potato' objects>,
'__weakref__': <attribute …Run Code Online (Sandbox Code Playgroud) python metaclass python-datamodel python-descriptors python-object
这个问题可能在某个地方有答案,但我找不到。
我用来setattr向类添加一长串描述符,并且我发现__set_name__当我使用setattr.
这对我来说不是一个大问题,因为我可以通过设置描述符的名称来代替__init__,我只是想了解为什么__set_name__不被调用,以及是否是因为我做错了什么。
class MyDescriptor:
def __set_name__(self, owner, name):
self._owner = owner
self._name = name
def __get__(self, instance, owner):
return self._name
class MyClass:
a = MyDescriptor()
setattr(MyClass, 'b', MyDescriptor()) # dynamically adding descriptor, __set_name__ is not called!
mc = MyClass()
print(mc.a) # prints 'a'
print(mc.b) # raises AttributeError: 'MyDescriptor' object has no attribute '_name'
Run Code Online (Sandbox Code Playgroud) 我偶然发现了这段代码,我觉得很奇怪,因为它似乎违反了 python 内置函数直接从对象的类调用 dunder 方法的事实。举__call__个例子,如果我们定义类A如下:
class A:\n @property\n def __call__(self):\n def inner():\n return 'Called.'\n return inner\n\na = A()\na() # return 'Called.'\n\ntype(a).__call__(a) # return 'property' object is not callable. \nRun Code Online (Sandbox Code Playgroud)\n然而,这种行为似乎与Python官方文档中所说的相矛盾:
\n\n\n\n
object.__call__(self[, args...])当实例\xe2\x80\x9c称为\xe2\x80\x9d\nas函数时调用;如果定义了此方法,则x(arg1, arg2, ...)大致\n转换为type(x).__call__(x, arg1, ...).
谁能解释一下这是怎么回事?
\n我一直在Descriptor HowTo Guide 中阅读有关描述符的内容,但我对这句话感到困惑:
如果实例的字典有一个与数据描述符同名的条目,则数据描述符优先。
字典如何包含两个具有相同名称的项目(一个普通条目和一个数据描述符)?或者作为描述符的属性没有存储在__dict__?
我有一个用例,我想用一种额外的调用方法来装饰一个方法,例如在以下代码中:
def decorator(func):
def enhanced(*args, **kwargs):
func(*args, **kwargs)
func.enhanced = enhanced
return func
@decorator
def function():
pass
class X:
@decorator
def function(self):
pass
x = X()
function()
function.enhanced()
x.function()
# x.function.enhanced()
x.function.enhanced(x)
Run Code Online (Sandbox Code Playgroud)
前三个调用按预期工作,但x.function.enhanced()没有;我必须写信x.function.enhanced(x)才能让它发挥作用。我知道这是因为func传递给装饰器的不是绑定方法而是函数,因此需要传递self显式传递。
但我该如何解决这个问题呢?从我对描述符的一点了解来看,它们仅在查找类时才相关,而func不是类,func.enhanced不会以我可以拦截的方式查找。
我在这里可以做些什么吗?
有许多方法装饰器的示例可以将方法转换为缓存的属性。但有时,我想检查缓存是否处于“活动”状态,这意味着该属性已被访问并且缓存已被填充。
例如,如果我使用rows缓存将 sql 表存储在 a 中rows,我想根据缓存计算表的长度(如果已填充),但如果没有填充,则通过单独的 sql 调用。如何在rows不触发访问的情况下检查是否已被访问?
这是一个很好的装饰器,取自 David Beazley 的“Python Cookbook”),我正在使用它来满足我的缓存属性需求。我已经增强了它以启用我当前的黑客。
class lazyprop:
def __init__(self, func):
self.func = func
def __get__(self, instance, cls):
if instance is None:
return self
else:
value = self.func(instance)
setattr(instance, self.func.__name__, value)
setattr(instance, self.func.__name__ + '__cache_active', True) # my hack
return value
Run Code Online (Sandbox Code Playgroud)
使用示例:
>>> class Test:
... def __init__(self, a):
... self.a = a
... @lazyprop
... def len(self):
... print('generating "len"')
... return len(self.a)
>>> t = …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个可以轻松扩展的模拟类。为此,我想使用类似于属性的东西,但这也提供了update一种可以针对不同用例以不同方式实现的方法:
class Quantity(object):
def __init__(self, initval=None):
self.value = initval
def __get__(self, instance, owner):
return self.value
def __set__(self, instance, value):
self.value = value
def update(self, parent):
"""here the quantity should be updated using also values from
MySimulation, e.g. adding `MySimulation.increment`, but I don't
know how to link to the parent simulation."""
class MySimulation(object):
"this default simulation has only density"
density = Quantity()
increment = 1
def __init__(self, value):
self.density = value
def update(self):
"""this one does not work because …Run Code Online (Sandbox Code Playgroud) 如此处所述:
https://docs.python.org/3/reference/datamodel.html#object.__get__
传递给 __get__ 方法的两个参数('self' 除外)分别是对象和访问属性的类。第二个论点不是多余的吗?此外,当“类”也是对象时,为什么需要区分对象和类访问?
所以,在我看来,有两种可能性:
在我看来,如果只使用一个参数(例如instance)可以实现相同的功能,该参数将始终保存原始对象,无论它是否是“类”。如果确实需要该信息,则可以使用isinstance(instance, type).
那么,为什么需要两个参数呢?
我需要一些有关 python 描述符的帮助。我编写了一个从 perl 到 python (Pythonizer) 的自动翻译器,并且我正在尝试实现绑定标量,它基本上是一个充当标量的对象,但具有适当调用的 FETCH 和 STORE 操作。我使用动态类命名空间“main”来存储变量值。我试图为该对象定义__get__和__set__操作,但它们不起作用。任何帮助将不胜感激!
main = type('main', tuple(), dict())\n\nclass TiedScalar(dict): # Generated code - can't be changed\n FETCH_CALLED_v = 0\n STORE_CALLED_v = 0\n\n def STORE(*_args):\n _args = list(_args)\n self = _args.pop(0) if _args else None\n TiedScalar.STORE_CALLED_v = TiedScalar.STORE_CALLED_v + 1\n self["value"] = _args.pop(0) if _args else None\n return self.get("value")\n \n \n #TiedScalar.STORE = lambda *_args, **_kwargs: perllib.tie_call(STORE, _args, _kwargs)\n \n \n def FETCH(*_args):\n _args = list(_args)\n self …Run Code Online (Sandbox Code Playgroud)