Ответ 1
как я должен структурировать класс, используя
__init__
и__new__
, поскольку они разные, и оба принимают произвольные аргументы, кроме первого аргумента по умолчанию.
Редко вам придется беспокоиться о __new__
. Обычно вы просто определяете __init__
и позволяете по умолчанию __new__
передавать ему аргументы конструктора.
self
ключевое слово в терминах имени может быть изменено на что-то еще? Но мне интересно, чтоcls
в терминах имени может быть изменено на что-то еще, поскольку это просто имя параметра?
Оба являются именами параметров, которые не имеют особого значения в языке. Но их использование - очень сильное соглашение в сообществе Python; большинство Pythonistas никогда не изменят имена self
и cls
в этих контекстах и будут смущены, если кто-то еще сделает.
Обратите внимание, что использование def __new__(tuple)
повторно связывает имя tuple
внутри функции конструктора. Когда вы выполняете __new__
, вы захотите сделать это как
def __new__(cls, *args, **kwargs):
# do allocation to get an object, say, obj
return obj
Хотя я сказал, что хочу вернуть
tuple
, этот код отлично работает и вернул мне[1,2,3]
.
MyClass()
будет иметь значение, возвращаемое __new__
. Там нет неявной проверки типов в Python; это ответственность программиста вернуть правильный тип ( "мы все соглашающиеся взрослые здесь). Возможность вернуть другой тип, чем запрошено, может быть полезна для реализации фабрик: вы можете вернуть подкласс запрашиваемого типа.
Это также объясняет поведение issubclass
/isinstance
, которое вы наблюдаете: отношение подкласса следует из вашего использования class MyClass(tuple)
, isinstance
отражает то, что вы возвращаете "неправильный" тип из __new__
.
Для справки ознакомьтесь с требованиями для __new__
в справочнике по языку Python.
Изменить: ok, вот пример потенциально полезного использования __new__
. Класс Eel
отслеживает, сколько угрей жив в процессе и отказывается выделять, если это превышает некоторый максимум.
class Eel(object):
MAX_EELS = 20
n_eels = 0
def __new__(cls, *args, **kwargs):
if cls.n_eels == cls.MAX_EELS:
raise HovercraftFull()
obj = super(Eel, cls).__new__(cls)
cls.n_eels += 1
return obj
def __init__(self, voltage):
self.voltage = voltage
def __del__(self):
type(self).n_eels -= 1
def electric(self):
"""Is this an electric eel?"""
return self.voltage > 0
Имейте в виду, что более интеллектуальные способы выполняют это поведение.