标签: python-datamodel

Python - 类__hash__方法和集合

我正在使用类set()__hash__方法python来防止在set中添加相同的哈希对象.根据python数据模型文档,set()将相同的哈希对象视为同一个对象,只需添加一次即可.

但它的行为如下:

class MyClass(object):

    def __hash__(self):
        return 0

result = set()
result.add(MyClass())
result.add(MyClass())

print(len(result)) # len = 2
Run Code Online (Sandbox Code Playgroud)

在字符串值的情况下,它可以正常工作.

result.add('aida')
result.add('aida')

print(len(result)) # len = 1
Run Code Online (Sandbox Code Playgroud)

我的问题是:为什么相同的哈希对象在集合中不相同?

python hash set python-datamodel python-3.x

11
推荐指数
2
解决办法
7713
查看次数

对象相等(`==`)的默认行为在哪里定义?

根据object.__eq__()文档,默认(即在object类中)实现==如下:

True if x is y else NotImplemented
Run Code Online (Sandbox Code Playgroud)

仍然遵循的文档NotImplemented,我推断这NotImplemented意味着 Python 运行时将尝试以相反的方式进行比较。y.__eq__(x)即如果x.__eq__(y)返回则尝试NotImplemented(在运算符的情况下==)。

现在,在 python 3.9 中False打印以下代码:True

class A:
   pass
print(A() == A())
print(bool(NotImplemented))
Run Code Online (Sandbox Code Playgroud)

所以我的问题如下:文档在哪里提到了NotImplemented在上下文中的特殊行为__eq__

PS:我在CPython 源代码中找到了答案,但我想这必须/应该在文档中的某个位置。

python python-datamodel python-internals

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

在python中获取对象的父命名空间?

在python中,可以使用'.' 为了访问对象的字典项.例如:

class test( object ) :
  def __init__( self ) :
    self.b = 1
  def foo( self ) :
    pass
obj = test()
a = obj.foo
Run Code Online (Sandbox Code Playgroud)

从上面的示例中,拥有'a'对象,是否有可能从它引用'obj',它是'foo'方法分配的父命名空间?例如,将obj.b更改为2?

python python-datamodel

9
推荐指数
3
解决办法
8715
查看次数

Python反射和类型转换

在Python中,str(),int(),float()等函数通常用于执行类型转换.但是,这些要求您在开发时了解要转换为的类型.我正在尝试编写的一些Python代码的子问题如下:

给出两个变量,foobar找到类型foo.(在开发时不知道,因为这是通用代码.)然后,尝试转换bar为任何类型foo.如果无法做到这一点,请抛出异常.

例如,假设您调用执行此操作的函数conv.它的签名看起来像

def conv(foo, bar) :
    # Do stuff.
Run Code Online (Sandbox Code Playgroud)

它会被称为:

result = conv(3.14, "2.718")  # result is now 2.718, as a float.
Run Code Online (Sandbox Code Playgroud)

python reflection introspection type-conversion python-datamodel

7
推荐指数
2
解决办法
5576
查看次数

没有任何描述符魔法的python属性查找?

我已经开始在我编写的代码中更广泛地使用python描述符协议.通常,默认的python查找魔法是我想要发生的,但有时我发现我想获取描述符对象本身而不是其__get__方法的结果.想知道描述符的类型,或者描述符中存储的访问状态,或者某些东西.

我编写了下面的代码,以我认为正确的顺序遍历名称空间,并返回属性raw,无论它是否是描述符.我很惊讶,虽然我无法在标准库中找到内置函数或其他内容来实现这一点 - 我认为它必须在那里,我只是没有注意到它或用Google搜索正确的搜索词.

python发行版中的某个地方是否有功能(或类似的东西)?

谢谢!

from inspect import isdatadescriptor

def namespaces(obj):
    obj_dict = None
    if hasattr(obj, '__dict__'):
        obj_dict = object.__getattribute__(obj, '__dict__')

    obj_class = type(obj)
    return obj_dict, [t.__dict__ for t in obj_class.__mro__]

def getattr_raw(obj, name):
    # get an attribute in the same resolution order one would normally,
    # but do not call __get__ on the attribute even if it has one
    obj_dict, class_dicts = namespaces(obj)

    # look for a data descriptor in class hierarchy; it takes priority over …
Run Code Online (Sandbox Code Playgroud)

python descriptor python-datamodel

7
推荐指数
1
解决办法
3196
查看次数

为什么Counter的__init__方法被称为描述符?

我正在阅读Counter类的__init__方法,并看到了这个:

if not args:
    TypeError("descriptor '__init__' of 'Counter' object "
              "needs an argument")
Run Code Online (Sandbox Code Playgroud)

我不确定描述符是什么意思,所以我检查了python数据模型文档,发现了这个:

通常,描述符是具有"绑定行为"的对象属性,其属性访问权已被描述符协议中的方法覆盖:__ get __(),__ set __()和__delete __().如果为对象定义了任何这些方法,则称其为描述符.

这些方法似乎都没有出现在类定义中,为什么__init_被称为描述符?

python python-datamodel python-3.x

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

模块命名空间中的定义顺序是否可用?

据记载,中的定义顺序被保留(参见PEP 520):

如果元类没有__prepare__属性,则将类命名空间初始化为空有序映射.

定义顺序是否也保留在模块对象中?

# foo_bar.py

def foo():
    pass

def bar():
    pass
Run Code Online (Sandbox Code Playgroud)

我已经尝试了上面的模块(也交换了顺序),它似乎确实可靠:

>>> import foo_bar
>>> for name in foo_bar.__dict__:
...     if not name.startswith('_'):
...         print(name)
... 
foo
bar
Run Code Online (Sandbox Code Playgroud)

据推测,该模块命名空间还采用了紧凑字典底下,或者从一个事实,即遵循type(foo_bar)<class 'module'>,它也必须尊重定义顺序,像任何其他类.但是,我不确定这是否是Python保证的功能,或者只是CPython实现细节. 模块中的名称是否需要遵守定义排序?

python python-module python-datamodel python-3.6

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

为什么Python没有"__req__"(反映相等)方法?

我有一个小助手班:

class AnyOf(object):
    def __init__(self, *args):
        self.elements = args
    def __eq__(self, other):
        return other in self.elements
Run Code Online (Sandbox Code Playgroud)

这让我做了甜蜜的魔术:

>>> arr = np.array([1,2,3,4,5])
>>> arr == AnyOf(2,3)
np.array([False, True, True, False, False])
Run Code Online (Sandbox Code Playgroud)

无需使用列表理解(如np.array(x in (2,3) for x in arr).

(我维护一个让(可信)用户输入任意代码的用户界面,并且a == AnyOf(1,2,3)比非技术精明用户的列表理解更加可口.)

然而!

这只适用于一种方式!例如,如果我这样做,AnyOf(2,3) == arr那么我的AnyOf类的__eq__方法永远不会被调用:相反,NumPy数组的__eq__方法被调用,在内部(我会假设)调用其__eq__所有元素的方法.

这让我想知道:为什么Python不允许右侧等效__eq__?(大致相当于像__radd__,__rmul__等等的方法.)

python numpy python-datamodel python-internals

6
推荐指数
2
解决办法
341
查看次数

何时可以将dict_values视图设置为set(为什么)?

文档说值视图不被视为set-like,但有时它们是:

>>> d = {1: 1}
>>> d.values() | d.keys() 
{1}
>>> d.values() & d.keys() 
{1}
>>> d.values() - d.keys() 
set()
Run Code Online (Sandbox Code Playgroud)

为什么要实现返回集合的集合语义,但随后却因实际集合而失败?

>>> d.values() - {1}
TypeError: unsupported operand type(s) for -: 'dict_values' and 'set'
Run Code Online (Sandbox Code Playgroud)

python dictionary set python-datamodel

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

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
查看次数