Phương pháp __dict__ là gì?
- Theo đối tượng tài liệu Python .__ Dict__ là một từ điển hoặc đối tượng ánh xạ khác được sử dụng để lưu trữ các thuộc tính đối tượng [có thể ghi].
- Hoặc nói bằng các từ đơn giản Mỗi đối tượng trong Python có một thuộc tính được ký hiệu là __dict__.
- Và đối tượng này chứa tất cả các thuộc tính được xác định cho đối tượng. __dict__ cũng được gọi là đối tượng ánh xạ.
Hãy xem xét các đối tượng Dict và Liệt kê trong Python cho phép sử dụng phương pháp này trong các đối tượng này.
Danh sách đạo đứcSử dụng phương thức __dict__ cho các đối tượng và lớp do người dùng xác định.
Vì từ mã trên, chúng ta có thể quan sát rằng khi __dict__ được gọi cho đối tượng của lớp học lớp, chúng ta sẽ nhận được từ điển cho các thuộc tính được xác định và khi cùng một hàm được gọi trực tiếp cho lớp, chúng ta sẽ nhận được tất cả các biến được xác định.
Bây giờ chúng ta hãy nói về chức năng Vars [] trong Python.
- Hàm Vars [đối tượng] trả về thuộc tính __dict__ của đối tượng như chúng ta biết thuộc tính __dict__ là một từ điển chứa các thuộc tính có thể thay đổi của đối tượng.
- Nếu không có giá trị nào được chỉ định cho hàm vars [], nó hoạt động như phương thức pythons locals [].
Gọi vars [] mà không có lập luận. Trong trường hợp này, chúng tôi đang xác định hai biến toàn cầu A và b.
a = "Hello"b = "World"vars[]varsvars
Như chúng ta đã biết vars [] cho chúng ta biểu diễn từ điển của tất cả các biến được xác định trong phạm vi của tập lệnh Python được xác định. Hãy gọi biến này cho các đối tượng sẵn có và các đối tượng do người dùng xác định. Điều này giống như gọi __dict__ trên đối tượng.
Ví dụ về vars [] [nội dung này là tùy chọn]
Bạn muốn tạo một chuỗi trong đó các tên biến được nhúng được thay thế bằng biểu diễn chuỗi của giá trị biến.
Trong ví dụ trên, phương pháp đầu tiên sử dụng một phương thức nổi tiếng để thay thế các biến nhưng phương thức thứ hai sử dụng hàm vars [] để thay thế các biến được xác định trong phạm vi của tập lệnh [phạm vi toàn cầu].
Chúng ta hãy xem phạm vi của tập lệnh bằng cách gọi vars [] ở đây chúng được xác định là dog_name và Eye_color được định nghĩa là cặp giá trị khóa trong phạm vi toàn cầu và định dạng sử dụng các khóa này để thay thế các giá trị này.
Bây giờ vấn đề chính với String.Format [] là nếu có những giá trị bị thiếu, chúng ta sẽ gặp lỗi. Do đó ở đây, chúng ta có thể tận dụng phương thức __Missing __ [] của chính Python. Các phần dưới được xác định dưới đây thừa kế đối tượng Dict và nếu khóa bị thiếu, chúng ta có thể đưa ra đầu ra tùy chỉnh của chúng ta.
References:
Tài liệu Python định nghĩa
class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
1 là:Một từ điển hoặc đối tượng ánh xạ khác được sử dụng để lưu trữ các thuộc tính đối tượng [có thể ghi].
Tuy nhiên, định nghĩa này hơi mờ, dẫn đến rất nhiều cách sử dụng sai
class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
1.Thật vậy, khi bạn đọc định nghĩa này, bạn có thể biết thuộc tính "có thể viết" là gì và những gì không?
Ví dụ
Chúng ta hãy chạy một vài ví dụ cho thấy nó khó hiểu và không chính xác như thế nào.
class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
Với lớp trên
class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
3 và biết định nghĩa của ____ 11, bạn có thể đoán giá trị của class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
5 không?
6 có phải là một thuộc tính có thể ghi củaclass A: foo = 1 def __init__[self]: self.bar = 2 @property def baz[self]: return self._baz @bar.setter def baz[self, value]: self._baz = value >>> a = A[] >>> a.foo 1 >>> a.bar 2
7 không?class A: foo = 1 def __init__[self]: self.bar = 2 @property def baz[self]: return self._baz @bar.setter def baz[self, value]: self._baz = value >>> a = A[] >>> a.foo 1 >>> a.bar 2
8 có phải là một thuộc tính có thể ghi củaclass A: foo = 1 def __init__[self]: self.bar = 2 @property def baz[self]: return self._baz @bar.setter def baz[self, value]: self._baz = value >>> a = A[] >>> a.foo 1 >>> a.bar 2
7 không?class A: foo = 1 def __init__[self]: self.bar = 2 @property def baz[self]: return self._baz @bar.setter def baz[self, value]: self._baz = value >>> a = A[] >>> a.foo 1 >>> a.bar 2
0 có phải là một thuộc tính có thể ghi của>>> a.__dict__ {'bar': 2}
7 không?class A: foo = 1 def __init__[self]: self.bar = 2 @property def baz[self]: return self._baz @bar.setter def baz[self, value]: self._baz = value >>> a = A[] >>> a.foo 1 >>> a.bar 2
2 có phải là thuộc tính có thể ghi của>>> a.__dict__ {'bar': 2}
7 không?class A: foo = 1 def __init__[self]: self.bar = 2 @property def baz[self]: return self._baz @bar.setter def baz[self, value]: self._baz = value >>> a = A[] >>> a.foo 1 >>> a.bar 2
Đây là câu trả lời:
>>> a.__dict__
{'bar': 2}
Đáng ngạc nhiên,
class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
6 không xuất hiện. Thật vậy, mặc dù có thể truy cập với >>> a.__dict__
{'bar': 2}
5, nhưng đó là một thuộc tính của lớp class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
3, không phải của ví dụ class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
7.Bây giờ điều gì xảy ra nếu chúng ta định nghĩa nó một cách rõ ràng là một thuộc tính của
class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
7?>>> a.foo = 1
>>> a.__dict__
{'bar': 2, 'foo': 1}
Từ quan điểm của chúng tôi, không có gì thực sự thay đổi,
>>> a.__dict__
{'bar': 2}
5 vẫn bằng >>> a.foo = 1
>>> a.__dict__
{'bar': 2, 'foo': 1}
0, nhưng bây giờ nó xuất hiện trong class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
1. Lưu ý rằng chúng ta có thể tiếp tục chơi với nó bằng cách xóa >>> a.__dict__
{'bar': 2}
5 chẳng hạn:>>> del a.foo
>>> a.__dict__
{'bar': 2}
>>> a.foo
1
Điều xảy ra ở đây là chúng tôi đã xóa thuộc tính thể hiện và gọi
>>> a.__dict__
{'bar': 2}
5 lại rơi trở lại >>> a.foo = 1
>>> a.__dict__
{'bar': 2, 'foo': 1}
4.Bây giờ chúng ta hãy xem
>>> a.__dict__
{'bar': 2}
0. Chúng tôi có thể giả định rằng chúng tôi không thể tìm thấy nó trong class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
5 vì chúng tôi chưa cho nó một giá trị.>>> a.baz = 3
Được rồi, bây giờ chúng tôi đã xác định
>>> a.foo = 1
>>> a.__dict__
{'bar': 2, 'foo': 1}
7. Vì vậy, >>> a.__dict__
{'bar': 2}
0 có phải là một thuộc tính có thể ghi không? Còn >>> a.__dict__
{'bar': 2}
2 thì sao?>>> a.__dict__
{'bar': 2, '_baz': 3}
Từ quan điểm của ____ 11,
>>> a.__dict__
{'bar': 2}
2 là một thuộc tính có thể ghi, nhưng >>> a.__dict__
{'bar': 2}
0 thì không. Giải thích, một lần nữa, là >>> a.__dict__
{'bar': 2}
0 là một thuộc tính của lớp class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
3, không phải là ví dụ class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
7.>>> A.__dict__['baz']
>>> a.foo = 1
>>> a.__dict__
{'bar': 2, 'foo': 1}
7 chỉ là một lớp trừu tượng gọi >>> del a.foo
>>> a.__dict__
{'bar': 2}
>>> a.foo
1
7 đằng sau hậu trường.Chúng ta còn lén lút hơn với người bạn thân yêu của chúng ta và thách thức định nghĩa "có thể viết" của nó.
class B:
def __init__[self]:
self.foobar = 'baz'
def __setattr__[self, name, value]:
if name == 'foobar' and 'foobar' in self.__dict__:
# Allow the first definition of foobar
# but prevent any subsequent redefinition
raise TypeError["'foobar' is a read-only attribute"]
super[].__setattr__[name, value]
>>> b = B[]
>>> b.foobar
'baz'
>>> b.foobar = 'bazbar'
TypeError: 'foobar' is a read-only attribute
>>> # From our developer's perspective, 'foobar' is not a writable attribute
>>> # But __dict__ doesn't share this point of view
>>> b.__dict__
{'foobar': 'baz'}
Vậy thì
1 chính xác là gì?class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
Nhờ các hành vi được chú ý trong các ví dụ trên, giờ đây chúng ta có thể hiểu rõ hơn về những gì
class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
1 thực sự làm. Nhưng chúng ta cần chuyển từ quan điểm của nhà phát triển sang quan điểm của máy tính:class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
1 chứa dữ liệu được lưu trữ trong bộ nhớ của chương trình cho đối tượng cụ thể này.the data stored in the program's memory for this specific object.Đó là nó,
class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
1 phơi bày những gì thực sự được lưu trữ trong bộ nhớ theo địa chỉ đối tượng của chúng tôi.Tài liệu Python trên mô hình dữ liệu cũng định nghĩa nó là không gian tên của đối tượng:
Một thể hiện lớp có một không gian tên được thực hiện như một từ điển là nơi đầu tiên trong đó các tài liệu tham khảo thuộc tính được tìm kiếm. Khi một thuộc tính không được tìm thấy ở đó và lớp thể hiện có một thuộc tính theo tên đó, tìm kiếm tiếp tục với các thuộc tính của lớp.
Tuy nhiên, tôi tin rằng đã nghĩ về
class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
1 vì bảng bộ nhớ của đối tượng mang lại hình dung tốt hơn nhiều về những gì được bao gồm trong không gian tên này và những gì không.Nhưng mà! Có một ... There is a catch...
Bạn nghĩ rằng chúng tôi đã hoàn thành với
1?class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
1 không phải là cách để đối phó với dấu chân bộ nhớ của đối tượng, mà là một cách.the way to deal with the object's memory footprint, but a way.Thực sự có một cách khác:
>>> a.baz = 3
5. Tôi sẽ không nêu chi tiết ở đây nó hoạt động như thế nào, đã có một câu trả lời rất đầy đủ về >>> a.baz = 3
5 nếu bạn muốn tìm hiểu thêm về nó. Nhưng điều quan trọng đối với chúng tôi là, nếu các khe được xác định:class C:
__slots__ = ['foo', 'bar']
def __init__[self]:
self.foo = 1
self.bar = 2
>>> c = C[]
>>> c.foo
1
>>> c.bar
2
>>> c.__dict__
AttributeError: 'C' object has no attribute '__dict__'
Chúng ta có thể nói "Tạm biệt" với
class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
1.Vậy khi nào tôi nên sử dụng
1?class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
Như chúng ta đã thấy,
class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
1 phải được nhìn thấy từ quan điểm của máy tính, không phải từ chỗ ngồi của nhà phát triển. Thường xuyên hơn không, những gì chúng tôi coi là "thuộc tính" của đối tượng của chúng tôi không được kết nối trực tiếp với những gì thực sự được lưu trữ trong bộ nhớ. Đặc biệt với việc sử dụng các thuộc tính hoặc >>> a.__dict__
{'bar': 2, '_baz': 3}
0 chẳng hạn, điều đó thêm một mức độ trừu tượng cho sự thoải mái của chúng tôi.Mặc dù việc sử dụng
class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
1 để kiểm tra các thuộc tính của một đối tượng sẽ hoạt động trong hầu hết các trường hợp tầm thường, chúng tôi không thể dựa vào 100% dựa vào nó. Đó là một sự xấu hổ cho một cái gì đó được sử dụng để viết logic chung.Trường hợp sử dụng của
class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
1 có lẽ nên được giới hạn trong việc kiểm tra nội dung bộ nhớ của đối tượng. Mà không quá phổ biến. Và hãy nhớ rằng class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
1 có thể không được xác định [hoặc thiếu một số thuộc tính thực sự được lưu trữ trong bộ nhớ] khi các khe được xác định.Nó cũng có thể rất hữu ích trong bảng điều khiển của Python để nhanh chóng kiểm tra các thuộc tính và phương thức của lớp. Hoặc các thuộc tính của một đối tượng [tôi biết tôi chỉ nói rằng chúng ta không thể dựa vào nó, nhưng trong bảng điều khiển quan tâm nếu nó thất bại đôi khi hoặc nếu nó không chính xác].
Cảm ơn nhưng ... làm thế nào để tôi duyệt thuộc tính của đối tượng của tôi sau đó?
Chúng tôi đã thấy rằng
class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
1 thường bị lạm dụng và chúng tôi không thể thực sự dựa vào nó để kiểm tra các thuộc tính của một đối tượng. Nhưng sau đó, cách chính xác để làm điều đó là gì? Có cách nào để duyệt một thuộc tính đối tượng từ quan điểm trừu tượng của nhà phát triển không?Đúng. Có một số cách để làm nội tâm, và cách chính xác sẽ phụ thuộc vào những gì bạn thực sự muốn có được. Các thuộc tính thể hiện, thuộc tính lớp, thuộc tính, thuộc tính riêng tư, thậm chí các phương thức, ... về mặt kỹ thuật, tất cả các thuộc tính này là thuộc tính và theo tình huống của bạn, bạn có thể muốn bao gồm một số nhưng loại trừ các thuộc tính khác. Bối cảnh cũng rất quan trọng. Có thể bạn đang sử dụng một thư viện đã phơi bày các thuộc tính bạn muốn thông qua API của họ.
Nhưng nói chung, bạn có thể dựa vào mô -đun
>>> a.__dict__
{'bar': 2, '_baz': 3}
5.class A:
foo = 1
def __init__[self]:
self.bar = 2
@property
def baz[self]:
return self._baz
@bar.setter
def baz[self, value]:
self._baz = value
>>> a = A[]
>>> a.foo
1
>>> a.bar
2
0