标签: python-descriptors

Python中的自适应描述符

我想在返回代理对象的类上创建某种描述符.索引时,代理对象检索对象的成员并将索引应用于它们.然后它返回总和.

例如,

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)

python numpy python-3.x python-descriptors

6
推荐指数
1
解决办法
165
查看次数

以声明方式设置类__name__

为什么不能以声明方式覆盖类名,例如使用不是有效标识符的类名?

>>> 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

6
推荐指数
1
解决办法
586
查看次数

Python:使用 setattr 添加描述符不会调用 __set_name__

这个问题可能在某个地方有答案,但我找不到。

我用来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 setattr python-descriptors

6
推荐指数
1
解决办法
433
查看次数

Python dunder 方法包​​装为属性

我偶然发现了这段代码,我觉得很奇怪,因为它似乎违反了 python 内置函数直接从对象的类调用 dunder 方法的事实。举__call__个例子,如果我们定义类A如下:

\n
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. \n
Run Code Online (Sandbox Code Playgroud)\n

然而,这种行为似乎与Python官方文档中所说的相矛盾:

\n
\n

object.__call__(self[, args...])当实例\xe2\x80\x9c称为\xe2\x80\x9d\nas函数时调用;如果定义了此方法,则x(arg1, arg2, ...)大致\n转换为type(x).__call__(x, arg1, ...).

\n
\n

谁能解释一下这是怎么回事?

\n

python python-datamodel python-descriptors

6
推荐指数
1
解决办法
89
查看次数

Python 属性和描述符

我一直在Descriptor HowTo Guide 中阅读有关描述符的内容,但我对这句话感到困惑:

如果实例的字典有一个与数据描述符同名的条目,则数据描述符优先。

字典如何包含两个具有相同名称的项目(一个普通条目和一个数据描述符)?或者作为描述符的属性没有存储在__dict__?

python descriptor python-3.x python-descriptors

5
推荐指数
1
解决办法
278
查看次数

装饰方法时访问绑定方法或 self

我有一个用例,我想用一种额外的调用方法来装饰一个方法,例如在以下代码中:

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不会以我可以拦截的方式查找。

我在这里可以做些什么吗?

python python-decorators python-descriptors

5
推荐指数
1
解决办法
819
查看次数

知道 python 缓存的属性是否已被访问而无需实际访问它

有许多方法装饰器的示例可以将方法转换为缓存的属性。但有时,我想检查缓存是否处于“活动”状态,这意味着该属性已被访问并且缓存已被填充。

例如,如果我使用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)

python python-descriptors

5
推荐指数
1
解决办法
2206
查看次数

如何在python中向描述符或属性添加方法

我正在尝试编写一个可以轻松扩展的模拟类。为此,我想使用类似于属性的东西,但这也提供了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)

python oop python-descriptors

5
推荐指数
1
解决办法
248
查看次数

“__get__”参数之一是多余的吗?

如此处所述:

https://docs.python.org/3/reference/datamodel.html#object.__get__

传递给 __get__ 方法的两个参数('self' 除外)分别是对象和访问属性的类。第二个论点不是多余的吗?此外,当“类”也是对象时,为什么需要区分对象和类访问?

所以,在我看来,有两种可能性:

  • 从对象访问属性,在这种情况下,所有者参数将等于type( instance ),因此它不会带来新信息
  • 从类(“类型”的对象)访问属性,在这种情况下,源对象仅位于所有者参数中,实例None

在我看来,如果只使用一个参数(例如instance)可以实现相同的功能,该参数将始终保存原始对象,无论它是否是“类”。如果确实需要该信息,则可以使用isinstance(instance, type).

那么,为什么需要两个参数呢?

python python-descriptors

5
推荐指数
1
解决办法
119
查看次数

python中用于实现perl的tie标量操作的描述符

我需要一些有关 python 描述符的帮助。我编写了一个从 perl 到 python (Pythonizer) 的自动翻译器,并且我正在尝试实现绑定标量,它基本上是一个充当标量的对象,但具有适当调用的 FETCH 和 STORE 操作。我使用动态类命名空间“main”来存储变量值。我试图为该对象定义__get____set__操作,但它们不起作用。任何帮助将不胜感激!

\n
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)

python python-descriptors

5
推荐指数
1
解决办法
158
查看次数