Будучи относительно новым для Python 2, я не уверен, как лучше всего организовать мои файлы классов наиболее «питоновским» способом. Я бы не спрашивал об этом, если бы не тот факт, что Python, кажется, имеет довольно много способов делать вещи, которые сильно отличаются от того, что я ожидал от языков, к которым я привык.
Первоначально я просто обращался с классами так, как я обычно обращался с ними в C # или PHP, что, конечно, заставило меня споткнуться повсюду, когда я в конце концов обнаружил изменчивые значения:
class Pants(object):
pockets = 2
pocketcontents = []
class CargoPants(Pants):
pockets = 200
p1 = Pants()
p1.pocketcontents.append("Magical ten dollar bill")
p2 = CargoPants()
print p2.pocketcontents
Ой! Не ожидал такого!
Я потратил много времени на поиск в Интернете и других источниках других проектов в поисках подсказок о том, как лучше организовать мои классы, и одна из вещей, которую я заметил, заключалась в том, что люди, кажется, объявляют множество своих переменных экземпляра — изменяемых или в противном случае - в конструкторе, а также довольно густо нагромождать аргументы конструктора по умолчанию.
После такого развития какое-то время я все еще немного чешу затылок по поводу незнакомости этого. Принимая во внимание то, на что идет язык python, чтобы сделать вещи более интуитивно понятными и очевидными, мне это кажется совершенно странным в тех немногих случаях, когда у меня есть довольно много атрибутов или множество аргументов конструктора по умолчанию, особенно когда я подклассы:
class ClassWithLotsOfAttributes(object):
def __init__(self, jeebus, coolness='lots', python='isgoodfun',
pythonic='nebulous', duck='goose', pants=None,
magictenbucks=4, datawad=None, dataload=None,
datacatastrophe=None):
if pants is None: pants = []
if datawad is None: datawad = []
if dataload is None: dataload = []
if datacatastrophe is None: datacatastrophe = []
self.coolness = coolness
self.python = python
self.pythonic = pythonic
self.duck = duck
self.pants = pants
self.magictenbucks = magictenbucks
self.datawad = datawad
self.dataload = dataload
self.datacatastrophe = datacatastrophe
self.bigness = None
self.awesomeitude = None
self.genius = None
self.fatness = None
self.topwise = None
self.brillant = False
self.strangenessfactor = 3
self.noisiness = 12
self.whatever = None
self.yougettheidea = True
class Dog(ClassWithLotsOfAttributes):
def __init__(self, coolness='lots', python='isgoodfun', pythonic='nebulous', duck='goose', pants=None, magictenbucks=4, datawad=None, dataload=None, datacatastrophe=None):
super(ClassWithLotsOfAttributes, self).__init__(coolness, python, pythonic, duck, pants, magictenbucks, datawad, dataload, datacatastrophe)
self.noisiness = 1000000
def quack(self):
print "woof"
Если оставить в стороне легкую глупость (я не могу помочь себе, когда готовлю эти искусственные примеры классов), предполагая, что у меня есть реальная потребность в наборе классов с таким количеством атрибутов, я полагаю, что мои вопросы таковы:
Каков самый, гм, «питоновский» способ объявления класса с таким количеством атрибутов? Лучше ли поместить их против класса, если значение по умолчанию неизменяемое, аля Pants.pockets, или лучше поместить их в конструктор, аля ClassWithLotsOfAttributes.noisiness?
Есть ли способ устранить необходимость переопределять значения по умолчанию для всех аргументов конструктора подкласса, как в Dog.__init__? Должен ли я вообще включать такое количество аргументов со значениями по умолчанию?