【问题标题】:How does Property work with Itemgetter im Python?属性如何与 Python 中的 Itemgetter 一起使用?
【发布时间】:2013-09-23 09:16:15
【问题描述】:

我正在学习蟒蛇。当谈到官方库中的集合模块时,我发现了 NamedTuple 的代码片段,如:

for i, name in enumerate(field_names):
    template += "        %s = _property(_itemgetter(%d), doc='Alias for field number %d')\n" % (name, i, i)

它是 NamedTuple 生成的代码的一部分。生成的代码如下:

name = property(itemgetter(0), doc='Alias for field number 0')
age = property(itemgetter(1), doc='Alias for field number 1')

这是我的问题:

Itemgetter(0) 是一个需要对象作为参数的函数。但是属性不会将任何参数传递给 itemgetter。那么这是如何工作的呢?

谢谢!

这是使用属性的全部代码:

class Person(tuple):
    'Person(name, age)' 

    __slots__ = () 

    _fields = ('name', 'age') 

    def __new__(_cls, name, age):
        'Create new instance of Person(name, age)'
        print sys._getframe().f_code.co_name

        return _tuple.__new__(_cls, (name, age)) 

    @classmethod
    def _make(cls, iterable, new=tuple.__new__, len=len):
        'Make a new Person object from a sequence or iterable'
        print sys._getframe().f_code.co_name

        result = new(cls, iterable)
        if len(result) != 2:
            raise TypeError('Expected 2 arguments, got %d' % len(result))
        return result 

    def __repr__(self):
        'Return a nicely formatted representation string'
        print sys._getframe().f_code.co_name

        return 'Person(name=%r, age=%r)' % self 

    def _asdict(self):
        'Return a new OrderedDict which maps field names to their values'
        print sys._getframe().f_code.co_name

        return OrderedDict(zip(self._fields, self)) 

    def _replace(_self, **kwds):
        'Return a new Person object replacing specified fields with new values'
        print sys._getframe().f_code.co_name

        result = _self._make(map(kwds.pop, ('name', 'age'), _self))
        if kwds:
            raise ValueError('Got unexpected field names: %r' % kwds.keys())
        return result 

    def __getnewargs__(self):
        'Return self as a plain tuple.  Used by copy and pickle.'
        print sys._getframe().f_code.co_name

        return tuple(self) 

    name = property(itemgetter(0), doc='Alias for field number 0')
    age = property(itemgetter(1), doc='Alias for field number 1')

【问题讨论】:

    标签: python collections properties namedtuple


    【解决方案1】:

    itemgetter 不是函数,它是一个实例可调用的类(参见 FineManual)。 property 实例将使用当前对象作为参数调用它(这就是属性的用途)。

    让我们总结一下……假设:

    point = tuple(1, 2)
    getx = itemgetter(0)
    

    point 传递给getx() 将返回point[0](实际上,point.__getitem__[0] 其中point[0] 是语法糖)

    现在如果我们继承 tuple 并添加一个 property:

    class Point(tuple):
        @property
        def x(self):
            return self[0]
    

    @decorator 语法实际上是 :

    的语法糖
    class Point(tuple):
        def x(self):
            return self[0]
        x = property(fget=x)
    

    所以函数x成为property实例的fget属性,类语句命名空间中的名称x被反弹到这个property实例。

    现在让我们创建一个Point 实例:

    point = Point(1, 2)
    

    然后在评估point.x时,属性查找规则会在Point(实际上在point.__class__)上找到“x”property对象,注意它有一个__get__()方法,并根据描述符协议将返回Point.x.__get__(point, Point.__class__) 的结果。由于property.__get__(obj, cls) 主要实现为return self.fget(obj),这将返回以point 调用的x 函数的结果为self 参数。爱荷华州:

    point.x
    

    等价于

    Point.x.__get__(point, point.__class__)
    

    相当于

    Point.x.fget(point)
    

    相当于(注意:这里的“x”指的是作为fget参数传递给propertyx函数,而不是Point.x

    x(point)
    

    相当于

    point[0]
    

    由于itemgetter(0)(point) 等同于point[0],因此可以看到x = property(itemgetter(0)) 的工作原理。

    【讨论】:

    • 谢谢布鲁诺。我附上了 NamedTuple 生成的代码。你的意思是整个 Person 对象会被粘贴到 itemgetter(0) 或 itemgetter(1) 函数作为参数?如果是这样,哪个项目将被视为项目 0 或项目 1?因为我认为它应该将 _fields 作为参数传递。谢谢。
    • 嗨,有没有人可以回答我的问题?谢谢!
    • 不会“粘贴”任何内容,itemgetter 不是函数。您首先需要了解 Python 的对象模型和属性查找规则,特别是描述符协议(它提供对计算属性的支持,包括方法和属性),没有人会在这里解释整个事情,因为它已经有很好的文档了。
    • 是的,但是 itemgetter(0) 将返回一个需要一个可迭代对象作为其参数的可调用对象,对吧?但通常,作为 fget 参数传递给属性的可调用对象是一个没有参数的函数。但在这种情况下,itemgetter(0) 返回的可调用对象——我们称之为 f,需要一个可迭代项。那么谁来做这件事以及如何做呢?在 Python 文档中,它定义了属性等价于:
    • def itemgetter(*items): if len(items) == 1: item = items[0] def g(obj): return obj[item] else: def g(obj): return tuple(obj[item] for item in items) 返回 g
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 2023-01-21
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    相关资源
    最近更新 更多