Що тільки мене вразило, походить від Рубі, - це те, що так званий метод класу і так званий метод примірника - це лише функція з семантичним значенням, застосованим до його першого параметра, який мовчки передається, коли функція викликається як метод об'єкт (тобтоobj.meth()
).
Зазвичай цей об'єкт повинен бути екземпляром, але не @classmethod
декоратором методу змінює правила для передачі класу. Ви можете викликати метод класу за екземпляром (це просто функція) - першим аргументом буде його клас.
Оскільки це лише функція , її можна оголосити лише один раз у будь-якій заданій області (тобто class
визначенні). Якщо випливає, таким чином, як сюрприз для Rubyist, ви не можете мати метод класу та метод екземпляра з тим самим іменем .
Врахуйте це:
class Foo():
def foo(x):
print(x)
Ви можете зателефонувати foo
на екземпляр
Foo().foo()
<__main__.Foo instance at 0x7f4dd3e3bc20>
Але не на уроці:
Foo.foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method foo() must be called with Foo instance as first argument (got nothing instead)
Тепер додайте @classmethod
:
class Foo():
@classmethod
def foo(x):
print(x)
Виклик до екземпляра тепер проходить його клас:
Foo().foo()
__main__.Foo
як і дзвінки в клас:
Foo.foo()
__main__.Foo
Це лише умова, яка диктує, що ми використовуємо self
для цього першого аргументу метод екземпляра та cls
метод класу. Я не використовував тут жодного випадку, щоб проілюструвати, що це просто аргумент. У Ruby self
- ключове слово.
Контраст з Ruby:
class Foo
def foo()
puts "instance method #{self}"
end
def self.foo()
puts "class method #{self}"
end
end
Foo.foo()
class method Foo
Foo.new.foo()
instance method #<Foo:0x000000020fe018>
Метод класу Python - це просто прикрашена функція, і ви можете використовувати ті самі методи, щоб створити власні декоратори . Оформлений метод обертає реальний метод (у разі @classmethod
його передає аргумент додаткового класу). Основний метод все ще існує, прихований, але все ще доступний .
виноска: я написав це після зіткнення імені між класом та методом екземпляра, що викликало мою цікавість. Я далеко не експерт з Python і хотів би прокоментувати, якщо щось із цього не так.