mirror of
https://github.com/satwikkansal/wtfpython
synced 2024-11-21 18:54:20 +01:00
Translate Methods equality and identity example
This commit is contained in:
parent
a32eaca58f
commit
6e246d1487
102
translations/README-ru.md
vendored
102
translations/README-ru.md
vendored
@ -1075,3 +1075,105 @@ False
|
||||
* Более подробное объяснение можно найти [здесь] (https://www.naftaliharris.com/blog/python-subclass-intransitivity/).
|
||||
|
||||
---
|
||||
|
||||
|
||||
### ▶ Равенство и тождество методов
|
||||
<!-- Example ID: 94802911-48fe-4242-defa-728ae893fa32 --->
|
||||
|
||||
1.
|
||||
```py
|
||||
class SomeClass:
|
||||
def method(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def classm(cls):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def staticm():
|
||||
pass
|
||||
```
|
||||
|
||||
**Результат:**
|
||||
```py
|
||||
>>> print(SomeClass.method is SomeClass.method)
|
||||
True
|
||||
>>> print(SomeClass.classm is SomeClass.classm)
|
||||
False
|
||||
>>> print(SomeClass.classm == SomeClass.classm)
|
||||
True
|
||||
>>> print(SomeClass.staticm is SomeClass.staticm)
|
||||
True
|
||||
```
|
||||
|
||||
Обращаясь к `classm` дважды, мы получаем одинаковый объект, но не *тот же самый*? Давайте посмотрим, что происходит
|
||||
с экземплярами `SomeClass`:
|
||||
|
||||
2.
|
||||
```py
|
||||
o1 = SomeClass()
|
||||
o2 = SomeClass()
|
||||
```
|
||||
|
||||
**Вывод:**
|
||||
```py
|
||||
>>> print(o1.method == o2.method)
|
||||
False
|
||||
>>> print(o1.method == o1.method)
|
||||
True
|
||||
>>> print(o1.method is o1.method)
|
||||
False
|
||||
>>> print(o1.classm is o1.classm)
|
||||
False
|
||||
>>> print(o1.classm == o1.classm == o2.classm == SomeClass.classm)
|
||||
True
|
||||
>>> print(o1.staticm is o1.staticm is o2.staticm is SomeClass.staticm)
|
||||
True
|
||||
```
|
||||
|
||||
Повторный доступ к `классу` или `методу` создает одинаковые, но не *те же самые* объекты для одного и того же экземпляра `какого-либо класса`.
|
||||
|
||||
#### 💡 Объяснение
|
||||
* Функции являются [дескрипторами](https://docs.python.org/3/howto/descriptor.html). Всякий раз, когда к функции обращаются как к
|
||||
атрибута, вызывается дескриптор, создавая объект метода, который "связывает" функцию с объектом, владеющим атрибутом. При вызове метод вызывает функцию, неявно передавая связанный объект в качестве первого аргумента
|
||||
(именно так мы получаем `self` в качестве первого аргумента, несмотря на то, что не передаем его явно).
|
||||
```py
|
||||
>>> o1.method
|
||||
<bound method SomeClass.method of <__main__.SomeClass object at ...>>
|
||||
```
|
||||
* При многократном обращении к атрибуту каждый раз создается объект метода! Поэтому `o1.method is o1.method` всегда ложно. Однако доступ к функциям как к атрибутам класса (в отличие от экземпляра) не создает методов; поэтому
|
||||
`SomeClass.method is SomeClass.method` является истинным.
|
||||
```py
|
||||
>>> SomeClass.method
|
||||
<function SomeClass.method at ...>
|
||||
```
|
||||
* `classmethod` преобразует функции в методы класса. Методы класса - это дескрипторы, которые при обращении к ним создают
|
||||
объект метода, который связывает *класс* (тип) объекта, а не сам объект.
|
||||
```py
|
||||
>>> o1.classm
|
||||
<bound method SomeClass.classm of <class '__main__.SomeClass'>>
|
||||
```
|
||||
* В отличие от функций, `classmethod` будет создавать метод и при обращении к нему как к атрибуту класса (в этом случае они
|
||||
привязываются к классу, а не к его типу). Поэтому `SomeClass.classm is SomeClass.classm` является ошибочным.
|
||||
```py
|
||||
>>> SomeClass.classm
|
||||
<bound method SomeClass.classm of <class '__main__.SomeClass'>>
|
||||
```
|
||||
* Объект-метод равен, если обе функции равны, а связанные объекты одинаковы. Поэтому
|
||||
`o1.method == o1.method` является истинным, хотя и не является одним и тем же объектом в памяти.
|
||||
* `staticmethod` преобразует функции в дескриптор "no-op", который возвращает функцию как есть. Методы-объекты
|
||||
никогда не создается, поэтому сравнение с `is` является истинным.
|
||||
```py
|
||||
>>> o1.staticm
|
||||
<function SomeClass.staticm at ...>
|
||||
>>> SomeClass.staticm
|
||||
<function SomeClass.staticm at ...>
|
||||
```
|
||||
* Необходимость создавать новые объекты "метод" каждый раз, когда Python вызывает методы экземпляра, и необходимость изменять аргументы
|
||||
каждый раз, чтобы вставить `self`, сильно сказывается на производительности.
|
||||
CPython 3.7 [решил эту проблему](https://bugs.python.org/issue26110), введя новые опкоды, которые работают с вызовом методов
|
||||
без создания временных объектов методов. Это используется только при фактическом вызове функции доступа, так что
|
||||
приведенные здесь фрагменты не затронуты и по-прежнему генерируют методы :)
|
||||
|
||||
---
|
||||
|
Loading…
Reference in New Issue
Block a user