如何检查类是否具有`' attr'的属性在实例`语法中

发布于 2025-01-23 09:09:17 字数 1215 浏览 0 评论 0原文

我希望能够在实例语法中使用'attr'来检查我的dataclass是否具有指定的属性,但我似乎无法使其正常工作。

我想要的是与熊猫的示例相同的行为

import pandas as pd

df = pd.DataFrame(columns=['a', 'b', 'c'])
print('a' in df)
True

,但仅适用于自定义数据级

from dataclasses import dataclass

@dataclass
class User:
    email: int
    password: str
    blocked_at: float = None
    
    def __getitem__(self, item):
        return getattr(self, item)

user = User('[email protected]', 'password')

print(user['email'])

'email' in user
[email protected]

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [35], in <cell line: 1>()
----> 1 'email' in user in User.__getitem__(self, item)
      7 def __getitem__(self, item):
----> 8     return getattr(self, item)

TypeError: getattr(): attribute name must be string

I want to be able to use the 'attr' in instance syntax to check if my dataclass has the specified attribute but I can't seem to make it work.

What I want is same behavior as this example with pandas

import pandas as pd

df = pd.DataFrame(columns=['a', 'b', 'c'])
print('a' in df)
True

But just for a custom dataclass

from dataclasses import dataclass

@dataclass
class User:
    email: int
    password: str
    blocked_at: float = None
    
    def __getitem__(self, item):
        return getattr(self, item)

user = User('[email protected]', 'password')

print(user['email'])

'email' in user
[email protected]

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [35], in <cell line: 1>()
----> 1 'email' in user in User.__getitem__(self, item)
      7 def __getitem__(self, item):
----> 8     return getattr(self, item)

TypeError: getattr(): attribute name must be string

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

猫烠⑼条掵仅有一顆心 2025-01-30 09:09:17

发生的事情是您没有定义正确的钩子。您要实现 _________________________________ a>。

因为您没有,所以操作员中的切换到后备模式:通过对象迭代,就好像它是序列,所以它尝试object [0],然后对象[1] 等。直到它击中indexError或找到等于您要测试的值的东西。因此,例外,因为item0

使用HASATTR而不是getAttr,因为您想要 boolean 结果。对于您的__ getItem __,您要确保将attributeError exceptions to keyError异常旋转,以保持接口一致:

from __future__ import annotations
from dataclasses import dataclass

@dataclass
class User:
    email: int
    password: str
    blocked_at: float = None

    def __getitem__(self, item: str) -> str | int | float | None:
        try:
            return getattr(self, item)
        except AttributeError:
            raise KeyError(item) from None
    
    def __contains__(self, item: str) -> bool:
        return hasattr(self, item)

demo:demo:

>>> user = User('[email protected]', 'password')
>>> print(user['email'])
[email protected]
>>> 'email' in user
True
>>> user["nonesuch"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 12, in __getitem__
KeyError: 'nonesuch'

请参阅<<<<<<<<< a href =“ https://docs.python.org/3/reference/expressions.html#membership-test-details” rel =“ nofollow noreferrer”> python Referitiations on in is会员测试操作 中的如何回到迭代:

对于不定定义的用户定义类__包含__()但确实定义__ __ iter __(), x in y 是true如果某些值z,则表达式x为z或x == z是正确的,则在迭代y 。如果在迭代期间提出了异常,则好像中的fust fust fust。


最后,尝试了旧式迭代协议:如果类定义__ getItem __() x中的 in is true如果和只有有一个非负整数索引i,以便x是y [i]或x == y [i],并且没有较低的整数索引提高了<<<代码> indexError 异常。 (如果提出了其他例外,则好像在提出的例外一样)。

What is happening is that you didn't define the correct hook. You want to implement the __contains__ method.

Because you didn't, the in operator switches to the fallback mode: iterating over the object as if it was a sequence, so it tries object[0],then object[1], etc. until it hits an IndexError or finds something that is equal to the value you were testing for. Hence, the exception, as item is 0.

Use hasattr instead of getattr, as you want a boolean result. And for your __getitem__, you want to make sure you turn AttributeError exceptions into KeyError exceptions, to keep the interface consistent:

from __future__ import annotations
from dataclasses import dataclass

@dataclass
class User:
    email: int
    password: str
    blocked_at: float = None

    def __getitem__(self, item: str) -> str | int | float | None:
        try:
            return getattr(self, item)
        except AttributeError:
            raise KeyError(item) from None
    
    def __contains__(self, item: str) -> bool:
        return hasattr(self, item)

Demo:

>>> user = User('[email protected]', 'password')
>>> print(user['email'])
[email protected]
>>> 'email' in user
True
>>> user["nonesuch"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 12, in __getitem__
KeyError: 'nonesuch'

See the Python reference section on membership test operations for the details on how in will fall back to iteration:

For user-defined classes which do not define __contains__() but do define __iter__(), x in y is True if some value z, for which the expression x is z or x == z is true, is produced while iterating over y. If an exception is raised during the iteration, it is as if in raised that exception.

Lastly, the old-style iteration protocol is tried: if a class defines __getitem__(), x in y is True if and only if there is a non-negative integer index i such that x is y[i] or x == y[i], and no lower integer index raises the IndexError exception. (If any other exception is raised, it is as if in raised that exception).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文