Hướng dẫn python getattr vs __dict__ - python getattr so với __dict__

Trong các ví dụ nguồn và vì vậy câu trả lời có một số mức độ hướng nội đối tượng Python, một mô hình phổ biến là:

getattr(some_object, attribute_name_string)

Có một lý do tại sao mô hình này được ưu tiên hơn:

some_object.__dict__[attribute_name_string]

Cái nào dường như trực tiếp hơn cho thấy những gì đang xảy ra? Có phải vì sau này quá gần với một triển khai cụ thể trong CPython có thể có thể thay đổi?

Câu hỏi ban đầu của NB đã xác định không chính xác thành ngữ phổ biến là: Original question incorrectly identified the popular idiom as:

some_object.__getattr__(attribute_name_string)

Đã hỏi ngày 7 tháng 1 năm 2015 lúc 12:44Jan 7, 2015 at 12:44

Zehnpaardzehnpaardzehnpaard

5.7932 huy hiệu vàng24 Huy hiệu bạc40 Huy hiệu đồng2 gold badges24 silver badges40 bronze badges

3

some_object.__getattr__ không phải là một mô hình phổ biến. getattr(some_object, attribute_name_string) là cách thích hợp để truy cập các thuộc tính động.not a common pattern. getattr(some_object, attribute_name_string) is the proper way of accessing attributes dynamically.

Không phải tất cả các trường hợp đều có thuộc tính some_object.__dict__[attribute_name_string] 0; Một lớp sử dụng some_object.__dict__[attribute_name_string] 1 chẳng hạn sẽ không có thuộc tính đó. Tiếp theo, các thuộc tính không nhất thiết phải được tìm thấy trong trường hợp, nhưng thay vào đó là thuộc tính lớp. some_object.__dict__[attribute_name_string] 2 sẽ tìm thấy những thứ đó, nhìn vào some_object.__dict__[attribute_name_string] 0 sẽ không tìm thấy chúng. Các thuộc tính trên lớp cũng có thể phụ thuộc vào giao thức mô tả.

Có thể có việc sử dụng để truy cập trực tiếp vào móc some_object.__dict__[attribute_name_string] 4 hoặc thuộc tính some_object.__dict__[attribute_name_string] 0, nhưng chúng chỉ được sử dụng chuyên ngành. some_object.__dict__[attribute_name_string] 4 chỉ được sử dụng nếu thuộc tính không được tìm thấy đầu tiên ở nơi khác, ví dụ (vì vậy đối với các thuộc tính không có trên lớp hoặc trong some_object.__dict__[attribute_name_string] 7).not present on the class or in some_object.__dict__[attribute_name_string] 7).

Đã trả lời ngày 7 tháng 1 năm 2015 lúc 12:45Jan 7, 2015 at 12:45

Martijn Pieters ♦ Martijn PietersMartijn Pieters

994K277 Huy hiệu vàng3915 Huy hiệu bạc3259 Huy hiệu đồng277 gold badges3915 silver badges3259 bronze badges

1

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 some_object.__dict__[attribute_name_string] 4và some_object.__dict__[attribute_name_string] 9phương pháp ma thuật.some_object.__dict__[attribute_name_string] 4some_object.__dict__[attribute_name_string] 9phương pháp ma thuật.

__getattr__

Python sẽ gọi some_object.__dict__[attribute_name_string] 4phươ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ó some_object.__dict__[attribute_name_string] 4phương pháp. Bây giờ trong chính khi tôi cố gắng truy cập cả hai some_object.__getattr__(attribute_name_string) 2và some_object.__getattr__(attribute_name_string) 3thuộc tính mọi thứ hoạt động tốt. Nhưng khi tôi cố gắng truy cập some_object.__getattr__(attribute_name_string) 4thuộc tính - Python cho tôisome_object.__getattr__(attribute_name_string) 5some_object.__dict__[attribute_name_string] 4phươ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ó some_object.__dict__[attribute_name_string] 4phương pháp. Bây giờ trong chính khi tôi cố gắng truy cập cả hai some_object.__getattr__(attribute_name_string) 2some_object.__getattr__(attribute_name_string) 3thuộc tính mọi thứ hoạt động tốt. Nhưng khi tôi cố gắng truy cập some_object.__getattr__(attribute_name_string) 4thuộc tính - Python cho tôisome_object.__getattr__(attribute_name_string) 5

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ó some_object.__dict__[attribute_name_string] 4phương pháp. Bây giờ khi tôi cố gắng truy cập some_object.__getattr__(attribute_name_string) 4thuộc tính - python trả về cho tôi bất cứ điều gì tôi đã thực hiện trong some_object.__dict__[attribute_name_string] 4phươ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.Đếmsome_object.__dict__[attribute_name_string] 4phương pháp. Bây giờ khi tôi cố gắng truy cập some_object.__getattr__(attribute_name_string) 4thuộc tính - python trả về cho tôi bất cứ điều gì tôi đã thực hiện trong some_object.__dict__[attribute_name_string] 4phươ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 some_object.__dict__[attribute_name_string] 9phương thức. Nếu bạn có some_object.__dict__[attribute_name_string] 9phươ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 some_object.__dict__[attribute_name_string] 9phươ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.some_object.__dict__[attribute_name_string] 9phương thức. Nếu bạn có some_object.__dict__[attribute_name_string] 9phươ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 some_object.__dict__[attribute_name_string] 9phươ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 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' 2ngoạ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 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' 2ngoại lệ sẽ tăng ngoại lệ. Nếu không, nó trả về thuộc tính đó.

class Count: def __init__(self,mymin,mymax): self.mymin=mymin self.mymax=mymax self.current=None def __getattribute__(self, item): if item.startswith('cur'): raise AttributeError return object.__getattribute__(self,item) # or you can use ---return super().__getattribute__(item) obj1 = Count(1,10) print(obj1.mymin) print(obj1.mymax) print(obj1.current)

Quan trọng: Để tránh đệ quy vô hạn trong some_object.__dict__[attribute_name_string] 9phươ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 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' 4hoặc >>> 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' 5không>>> 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' 6some_object.__dict__[attribute_name_string] 9phươ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 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' 4hoặc >>> 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' 5không>>> 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' 6

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ì some_object.__dict__[attribute_name_string] 9được gọi đầu tiên. Nhưng nếu some_object.__dict__[attribute_name_string] 9tăng >>> 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' 2ngoại lệ thì ngoại lệ sẽ bị bỏ qua và some_object.__dict__[attribute_name_string] 4phương thức sẽ được gọi. Xem ví dụ sau:phương thức ma thuật getattrgetattribution thì some_object.__dict__[attribute_name_string] 9được gọi đầu tiên. Nhưng nếu some_object.__dict__[attribute_name_string] 9tăng >>> 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' 2ngoại lệ thì ngoại lệ sẽ bị bỏ qua và some_object.__dict__[attribute_name_string] 4phương thức sẽ được gọi. Xem ví dụ sau:

class Count(object): def __init__(self,mymin,mymax): self.mymin=mymin self.mymax=mymax self.current=None def __getattr__(self, item): self.__dict__[item]=0 return 0 def __getattribute__(self, item): if item.startswith('cur'): raise AttributeError return object.__getattribute__(self,item) # or you can use ---return super().__getattribute__(item) # note this class subclass object obj1 = Count(1,10) print(obj1.mymin) print(obj1.mymax) print(obj1.current)

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

Chủ đề