标签: python-descriptors

当@classmethod是什么时,为什么@staticmethod不会跨类保留?

采用以下示例脚本:

class A(object):
    @classmethod
    def one(cls):
        print("I am class")

    @staticmethod
    def two():
        print("I am static")


class B(object):
    one = A.one
    two = A.two


B.one()
B.two()
Run Code Online (Sandbox Code Playgroud)

当我使用Python 2.7.11运行此脚本时,我得到:

I am class
Traceback (most recent call last):
  File "test.py", line 17, in <module>
    B.two()
TypeError: unbound method two() must be called with B instance as first argument (got nothing instead)
Run Code Online (Sandbox Code Playgroud)

似乎@classmethod装饰器在类中保留,但@staticmethod不是.

Python 3.4的行为符合预期:

I am class
I am static
Run Code Online (Sandbox Code Playgroud)

为什么Python2不能保留@staticmethod,是否有解决方法?

编辑:从课堂上取两个(并保留@staticmethod)似乎有效,但这对我来说似乎仍然很奇怪.

python static-methods class-method python-2.7 python-descriptors

23
推荐指数
2
解决办法
1055
查看次数

Python 3.11+ 中的类属性

@classmethod在 Python 3.9 中,我们获得了链接和@property合理创建类属性的能力。

\n
class Foo:\n  @property\n  def instance_property(self):\n    return "A regular property"\n\n  @classmethod\n  @property\n  def class_property(cls):\n    return "A class property"\n
Run Code Online (Sandbox Code Playgroud)\n

这是通过与描述符协议进行适当的交互来实现的@classmethod,这意味着一个人的前景不仅限于@property阳光下的任何描述符。一切都很好,直到发现该实现导致了“许多下游问题”,并在 Python 3.11 中弃用。

\n

我已经阅读了一些关于弃用的GitHub 讨论,并且不会在这里抱怨我所说的仓促撤回仓促设计。事实上,类属性是人们想要的合理的东西,并且可以在 Python 3.9/3.10 中使用,但现在不能。发行说明建议如下:

\n
\n

要 \xe2\x80\x9cpass-through\xe2\x80\x9d 类方法,请考虑使用 Python 3.10 中添加的 __wrapped__ 属性。

\n
\n

如果说这样的句子本身极其无益,那就不会引起争议。描述符协议不是普通用户需要或想要遇到的东西,因此@classmethod通过自定义实现与它们链接肯定是那些了解情况的人可以并且会花时间弄清楚如何在 3.11+ 中正确执行的操作。

\n

但是对于那些不知道@property除了允许他们删除括号的东西之外还有什么的人来说,如何在 Python 3.11+ 中定义类属性,特别是如何做得好?

\n

python properties python-3.x python-decorators python-descriptors

18
推荐指数
1
解决办法
4536
查看次数

如何暂时分配成员变量?

我经常发现我需要临时分配一些成员变量,例如

old_x = c.x
old_y = c.y
# keep c.z unchanged

c.x = new_x
c.y = new_y

do_something(c)

c.x = old_x
c.y = old_y
Run Code Online (Sandbox Code Playgroud)

但我希望我能简单地写一下

with c.x = new_x; c.y = new_y:
    do_something(c)
Run Code Online (Sandbox Code Playgroud)

甚至

do_something(c with x = new_x; y = new_y)
Run Code Online (Sandbox Code Playgroud)

Python的装饰器或其他语言功能能够实现这种模式吗?(我可以c根据需要修改课程)

python python-2.7 python-decorators python-descriptors

12
推荐指数
2
解决办法
642
查看次数

python数据和非数据描述符

根据Python的文档,

带有__set__()__get__()定义的数据描述符总是覆盖实例字典中的重定义.

我理解这句话没有问题,但是有人可以为我澄清为什么会有这样的规则吗?毕竟,如果我想覆盖实例字典中的属性,我已经需要明确地执行(inst.__dict__["attr"] = val),因为天真inst.attr = val会调用描述符的__set__方法,这通常会覆盖实例字典中的属性.

编辑:为了说清楚,我理解发生了什么,我的问题是为什么这样的规则到位.

python descriptor python-descriptors

11
推荐指数
1
解决办法
1780
查看次数

为什么人们在__get__中将所有者参数默认为无?

我经常看到这个:

def __get__(self, instance, owner=None):
Run Code Online (Sandbox Code Playgroud)

为什么有些人使用的默认值None的的owner参数?

这甚至可以在Python文档中完成:

descr.__get__(self, obj, type=None) --> value
Run Code Online (Sandbox Code Playgroud)

python descriptor python-3.x python-descriptors

10
推荐指数
2
解决办法
458
查看次数

为什么在类上设置描述符会覆盖描述符?

简单再现:

class VocalDescriptor(object):
    def __get__(self, obj, objtype):
        print('__get__, obj={}, objtype={}'.format(obj, objtype))
    def __set__(self, obj, val):
        print('__set__')

class B(object):
    v = VocalDescriptor()

B.v # prints "__get__, obj=None, objtype=<class '__main__.B'>"
B.v = 3 # does not print "__set__", evidently does not trigger descriptor
B.v # does not print anything, we overwrote the descriptor
Run Code Online (Sandbox Code Playgroud)

这个问题有一个有效的重复项,但是没有回答重复项,作为学习练习,我对CPython源码进行了更多研究。警告:我进入了杂草。我真希望我能从知道这些水域的船长那里得到帮助。为了我自己的未来利益和未来读者的利益,我试图尽可能明确地追踪正在寻找的电话。

我已经看到很多墨水溅到了__getattribute__应用于描述符的行为上,例如查找优先级。Python的片断在“援引描述符”下方For classes, the machinery is in type.__getattribute__()...大致在我的脑海里同意我认为是相应的CPython的源type_getattro,我找到了通过看“tp_slots”然后tp_getattro填充其中B.v …

python cpython python-descriptors

10
推荐指数
1
解决办法
137
查看次数

在Python中使用描述符协议时如何获取属性名称?

描述符协议工作正常但我仍然有一个问题我想解决.

我有一个描述符:

class Field(object):
    def __init__(self, type_, name, value=None, required=False):
        self.type = type_
        self.name = "_" + name
        self.required = required
        self._value = value

    def __get__(self, instance, owner):
        return getattr(instance, self.name, self.value)

    def __set__(self, instance, value):
        if value:
            self._check(value)
            setattr(instance, self.name, value)
        else:
            setattr(instance, self.name, None)

    def __delete__(self, instance):
        raise AttributeError("Can't delete attribute")

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, value):
        self._value = value if value else self.type()

    @property
    def _types(self):
        raise NotImplementedError

    def _check(self, value):
        if not isinstance(value, …
Run Code Online (Sandbox Code Playgroud)

python descriptor python-descriptors

9
推荐指数
1
解决办法
7342
查看次数

获取描述符对象的简洁方法

在Python 3中

class A(object):
    attr = SomeDescriptor()
    ...
    def somewhere(self):
        # need to check is type of self.attr is SomeDescriptor()
        desc = self.__class__.__dict__[attr_name]
        return isinstance(desc, SomeDescriptor)
Run Code Online (Sandbox Code Playgroud)

有更好的方法吗?我不喜欢这个self.__class__.__dict__东西

python descriptor python-3.x python-descriptors

8
推荐指数
2
解决办法
1474
查看次数

使用描述符进行类型提示

这个拉取请求中,似乎添加了对描述符的类型提示支持。

但是,似乎从未发布过最终的“正确”使用示例,也似乎从未将任何文档添加到typing模块Mypy 中

看起来像的正确用法是像这样

from typing import TypeVar

T = TypeVar('T')
V = TypeVar('V')


class classproperty():
    def __init__(self, getter: Callable[[Type[T]], V]) -> None:
        self.getter = getter

    def __get__(self, instance: Optional[T], owner: Type[T]) -> V:
        return self.getter(owner)


def forty_two(cls: Type) -> int:
    return 42


class C:
    forty_two: int = classproperty(forty_two)
Run Code Online (Sandbox Code Playgroud)

这似乎合乎逻辑,但我不知道这是否真的是正确的做事方式。

有没有这方面的文件?或者实际适用于合并版本的完整示例?

python type-hinting python-3.x python-descriptors mypy

8
推荐指数
1
解决办法
1145
查看次数

键入:如何将所有者类绑定到通用描述符?

我可以在 Python 中以支持/尊重/理解其所有者的继承层次结构的方式实现通用描述符吗?

在代码中应该更清楚:

from typing import (
    Generic, Optional, TYPE_CHECKING,
    Type, TypeVar, Union, overload,
)

T = TypeVar("T", bound="A")  # noqa

class Descr(Generic[T]):

    @overload
    def __get__(self: "Descr[T]", instance: None, owner: Type[T]) -> "Descr[T]": ...

    @overload
    def __get__(self: "Descr[T]", instance: T, owner: Type[T]) -> T: ...

    def __get__(self: "Descr[T]", instance: Optional[T], owner: Type[T]) -> Union["Descr[T]", T]:
        if instance is None:
            return self
        return instance


class A:
    attr: int = 123
    descr = Descr[T]()  # I want to bind T here, …
Run Code Online (Sandbox Code Playgroud)

python type-hinting python-descriptors mypy python-typing

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