Hướng dẫn python __getattr__ vs __getitem__ - trăn __getattr__ so với __getitem__

Tuyên bố miễn trừ trách nhiệm Đây chỉ là một bài tập trong lập trình meta, nó không có mục đích thực tế.

Tôi đã chỉ định các phương thức

>>> foo.baz
'baz'
2 và
>>> foo.baz
'baz'
3 trên một đối tượng hàm, nhưng không có hiệu lực ...

def foo():
  print "foo!"

foo.__getitem__ = lambda name: name
foo.__getattr__ = lambda name: name
foo.baz = 'baz'

Kiểm tra sự tỉnh táo rằng chúng ta có thể gán các thuộc tính cho một hàm:

>>> foo.baz
'baz'

Gọn gàng. Làm thế nào về "Getters ma thuật"?

>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

Có thể có một "getter ma thuật" trên một đối tượng chức năng?

Khi được hỏi ngày 29 tháng 5 năm 2012 lúc 16:48May 29, 2012 at 16:48

Hướng dẫn python __getattr__ vs __getitem__ - trăn __getattr__ so với __getitem__

Không! Việc gán

>>> foo.baz
'baz'
2 cho một thể hiện không hoạt động trên bất kỳ loại đối tượng nào:

>>> class A(object):
...   pass
...
>>> a = A()
>>> a.__getattr__ = lambda name: name
>>> a.foo
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'A' object has no attribute 'foo'

Và bạn không thể xác định

>>> foo.baz
'baz'
3 trên loại chức năng tích hợp: you can't define
>>> foo.baz
'baz'
3 on the built-in function type:

>>> import types
>>> types.FunctionType.__getitem__ = lambda name: name
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can't set attributes of built-in/extension type 'function'

Và bạn không thể phân nhóm

>>> foo.baz
'baz'
6: you can't subclass
>>> foo.baz
'baz'
6:

>>> import types
>>> class F(types.FunctionType):
...   pass
... 
Traceback (most recent call last):
  File "", line 1, in 
TypeError: Error when calling the metaclass bases
type 'function' is not an acceptable base type

Đã trả lời ngày 29 tháng 5 năm 2012 lúc 16:48May 29, 2012 at 16:48

Colintacolintacolinta

3,4671 Huy hiệu vàng27 Huy hiệu bạc18 Huy hiệu đồng1 gold badge27 silver badges18 bronze badges

1

Ít nhất là trên các lớp học theo phong cách mới (là loại duy nhất trong Python 3 và loại bạn nên sử dụng trong Python 2), Python chỉ tìm kiếm các phương pháp ma thuật trên lớp (và tổ tiên của nó), không bao giờ có trong trường hợp. Tài liệu ở đây.

Và tất nhiên bạn không thể sửa đổi loại chức năng hoặc xuất phát từ nó. Tuy nhiên, như bạn đã tìm thấy, bất kỳ lớp nào có phương thức

>>> foo.baz
'baz'
7 đều tạo ra các trường hợp có thể gọi được, vì vậy đó là cách để thực hiện.

Đã trả lời ngày 29 tháng 5 năm 2012 lúc 17:14May 29, 2012 at 17:14

Kindallkindallkindall

173K34 Huy hiệu vàng268 Huy hiệu bạc 301 Huy hiệu đồng34 gold badges268 silver badges301 bronze badges

3

Ahha! Sử dụng

>>> foo.baz
'baz'
8 và bọc chức năng trong
>>> foo.baz
'baz'
9

class F(object):
    def __init__(self, fn):
        self.__dict__['fn'] = fn

    def __call__(self, *args, **kwargs):
        return self.fn(*args, **kwargs)

    def __getitem__(self, name):
        return name

    def __getattr__(self, name):
        return name

>>> foo = F(foo)
>>> f.bar
'bar'
>>> f['foo']
'foo'
>>> foo()
foo!

Đã trả lời ngày 29 tháng 5 năm 2012 lúc 16:58May 29, 2012 at 16:58

Colintacolintacolinta

3,4671 Huy hiệu vàng27 Huy hiệu bạc18 Huy hiệu đồng1 gold badge27 silver badges18 bronze badges

7

Description¶

Called when an attribute lookup has not found the attribute in the usual places (i.e. it is not an instance attribute nor is it found in the class tree for self).

Syntax¶

object. __getattr__(self, name). __getattr__(self, name)

selfRequired. Instance of the class, passed automatically on call.nameRequired. The name of the attribute.

Example¶

>>> class Frob:
...     def __init__(self, bamf):
...         self.bamf = bamf
...     def __getattr__(self, name):
...         return 'Frob does not have `{}` attribute.'.format(str(name))
...
>>> f = Frob("bamf")
>>> f.bar
'Frob does not have `bar` attribute.'
>>> f.bamf
'bamf'

Hãy xem một số ví dụ đơn giản về cả hai

>>> foo.baz
'baz'
3và
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
1phương pháp ma thuật.
>>> foo.baz
'baz'
3
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
1phương pháp ma thuật.

__getattr__

Python sẽ gọi

>>> foo.baz
'baz'
3phương thức bất cứ khi nào bạn yêu cầu một thuộc tính chưa được xác định. Trong ví dụ sau lớp học của tôi Đếm không có
>>> foo.baz
'baz'
3phương pháp. Bây giờ trong chính khi tôi cố gắng truy cập cả hai
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
4và
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
5thuộc tính mọi thứ hoạt động tốt. Nhưng khi tôi cố gắng truy cập
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
6thuộc tính - Python cho tôi
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
7
>>> foo.baz
'baz'
3phương thức bất cứ khi nào bạn yêu cầu một thuộc tính chưa được xác định. Trong ví dụ sau lớp học của tôi Đếm không có
>>> foo.baz
'baz'
3phương pháp. Bây giờ trong chính khi tôi cố gắng truy cập cả hai
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
4
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
5thuộc tính mọi thứ hoạt động tốt. Nhưng khi tôi cố gắng truy cập
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
6thuộc tính - Python cho tôi
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
7

class Count():
    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent)  --> AttributeError: 'Count' object has no attribute 'mycurrent'

Bây giờ lớp học của tôi Đếm có

>>> foo.baz
'baz'
3phương pháp. Bây giờ khi tôi cố gắng truy cập
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
6thuộc tính - python trả về cho tôi bất cứ điều gì tôi đã thực hiện trong
>>> foo.baz
'baz'
3phương thức của mình . Trong ví dụ của tôi bất cứ khi nào tôi cố gắng gọi một thuộc tính không tồn tại, python tạo thuộc tính đó và đặt nó thành giá trị nguyên 0.Đếm
>>> foo.baz
'baz'
3phương pháp. Bây giờ khi tôi cố gắng truy cập
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
6thuộc tính - python trả về cho tôi bất cứ điều gì tôi đã thực hiện trong
>>> foo.baz
'baz'
3phương thức của mình . Trong ví dụ của tôi bất cứ khi nào tôi cố gắng gọi một thuộc tính không tồn tại, python tạo thuộc tính đó và đặt nó thành giá trị nguyên 0.

class Count:
    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax    

    def __getattr__(self, item):
        self.__dict__[item]=0
        return 0

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent1)

__getattribute__

Bây giờ hãy xem

>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
1phương thức. Nếu bạn có
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
1phương thức trong lớp, python gọi phương thức này cho mọi thuộc tính bất kể nó có tồn tại hay không. Vậy tại sao chúng ta cần
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
1phương pháp? Một lý do chính là bạn có thể ngăn truy cập vào các thuộc tính và làm cho chúng an toàn hơn như trong ví dụ sau.
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
1phương thức. Nếu bạn có
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
1phương thức trong lớp, python gọi phương thức này cho mọi thuộc tính bất kể nó có tồn tại hay không. Vậy tại sao chúng ta cần
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
1phương pháp? Một lý do chính là bạn có thể ngăn truy cập vào các thuộc tính và làm cho chúng an toàn hơn như trong ví dụ sau.

Bất cứ khi nào ai đó cố gắng truy cập các thuộc tính của tôi bắt đầu bằng chuỗi con trăn 'cur', chuỗi

>>> class A(object):
...   pass
...
>>> a = A()
>>> a.__getattr__ = lambda name: name
>>> a.foo
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'A' object has no attribute 'foo'
4ngoại lệ sẽ tăng ngoại lệ. Nếu không, nó trả về thuộc tính đó.trăn 'cur', chuỗi
>>> class A(object):
...   pass
...
>>> a = A()
>>> a.__getattr__ = lambda name: name
>>> a.foo
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'A' object has no attribute 'foo'
4ngoại lệ sẽ tăng ngoại lệ. Nếu không, nó trả về thuộc tính đó.

>>> foo.baz
'baz'
0

Quan trọng: Để tránh đệ quy vô hạn trong

>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
1phương thức, việc triển khai nó phải luôn gọi phương thức lớp cơ sở có cùng tên để truy cập bất kỳ thuộc tính nào mà nó cần. Ví dụ:
>>> class A(object):
...   pass
...
>>> a = A()
>>> a.__getattr__ = lambda name: name
>>> a.foo
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'A' object has no attribute 'foo'
6hoặc
>>> class A(object):
...   pass
...
>>> a = A()
>>> a.__getattr__ = lambda name: name
>>> a.foo
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'A' object has no attribute 'foo'
7không
>>> class A(object):
...   pass
...
>>> a = A()
>>> a.__getattr__ = lambda name: name
>>> a.foo
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'A' object has no attribute 'foo'
8
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
1phương thức, việc triển khai nó phải luôn gọi phương thức lớp cơ sở có cùng tên để truy cập bất kỳ thuộc tính nào mà nó cần. Ví dụ:
>>> class A(object):
...   pass
...
>>> a = A()
>>> a.__getattr__ = lambda name: name
>>> a.foo
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'A' object has no attribute 'foo'
6hoặc
>>> class A(object):
...   pass
...
>>> a = A()
>>> a.__getattr__ = lambda name: name
>>> a.foo
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'A' object has no attribute 'foo'
7không
>>> class A(object):
...   pass
...
>>> a = A()
>>> a.__getattr__ = lambda name: name
>>> a.foo
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'A' object has no attribute 'foo'
8

QUAN TRỌNG

Nếu lớp của bạn chứa cả phương thức ma thuật getattr và getattribution thì

>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
1được gọi đầu tiên. Nhưng nếu
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
1tăng
>>> class A(object):
...   pass
...
>>> a = A()
>>> a.__getattr__ = lambda name: name
>>> a.foo
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'A' object has no attribute 'foo'
4ngoại lệ thì ngoại lệ sẽ bị bỏ qua và
>>> foo.baz
'baz'
3phương thức sẽ được gọi. Xem ví dụ sau:phương thức ma thuật getattrgetattribution thì
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
1được gọi đầu tiên. Nhưng nếu
>>> foo.bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'bar'
1tăng
>>> class A(object):
...   pass
...
>>> a = A()
>>> a.__getattr__ = lambda name: name
>>> a.foo
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'A' object has no attribute 'foo'
4ngoại lệ thì ngoại lệ sẽ bị bỏ qua và
>>> foo.baz
'baz'
3phương thức sẽ được gọi. Xem ví dụ sau:

>>> foo.baz
'baz'
1

93 hữu ích 1 bình luận chia sẻ 1 bình luận chia sẻ