Добавление атрибутов класса с помощью цикла for в Python

Я пытался создать класс из словаря:

class attr:
    for key in objects_type:
        setattr(attr, key, lambda cl: list())

Это дает ошибку, заключающуюся в том, что attr не определен во время цикла for. Я знаю, что могу написать:

class attr:
    pass
for key in objects_type:
    setattr(attr, key, lambda cl: list())

Но я уверен, что где-то видел код, похожий на первый пример. Кто-нибудь знает, можно ли написать что-то похожее на первую форму?


person Casebash    schedule 15.02.2010    source источник


Ответы (5)


Хотя это не очень элегантно, вы можете использовать locals():

>>> class c(object):
...     for i in range(10):
...         locals()['A' + str(i)] = i
... 
>>> c.A0
0
>>> c.A7
7
person Max Shawabkeh    schedule 15.02.2010
comment
Должно быть, я это видел. Спасибо - person Casebash; 15.02.2010
comment
На самом деле, я думаю, что это лучше, чем использование setattr, поэтому я бы вообще не сказал, что это неэлегантно. - person Casebash; 15.02.2010
comment
Вы не должны изменять locals () dict: docs.python.org/library/ functions.html # locals - person stephan; 15.02.2010
comment
Я забыл об этом :-(. Как вы считаете риск поломки? - person Casebash; 15.02.2010

Я точно не знаю, что вы делаете. Я могу привести пример добавления атрибутов класса к классу в цикле for:

attributes = ('x', 5), ('y', 6), ('name', 'Cls')

class Cls:
  pass
for key, value in attributes:
  setattr(Cls, key, value)

Помните, что for должен запускаться после определения всего класса. Вы получаете сообщение об ошибке, что attr не определен, потому что вы хотите получить доступ к классу до его создания (class ... - это инструкция в python, которая создает объект класса). Вы должны добавить атрибуты после создания класса и запоминания, это будут атрибуты класса, а не атрибуты экземпляра.

person gruszczy    schedule 15.02.2010

предположим, вы хотите динамически добавлять атрибуты класса, такие как эти

classDict = {}
for i in range(2):
    classDict["func%s"%(i+1)] = lambda self:"X"

вы можете сделать это несколькими способами, например. просто добавьте атрибуты после создания класса, потому что вы можете легко получить доступ к имени класса внутри класса

class Attr2(object):
    pass

for n,v in classDict.iteritems():
    setattr(Attr2, n, v)

print Attr2().func1(), Attr2().func2()

или лучше просто создать класс на лету, например.

Attr3 = type("Attr3",(), classDict)
print Attr3().func1(), Attr3().func2()

или если вы хотите использовать метакласс, например

class AttrMeta(type):
    def __new__(cls, name, bases, dct):
        dct.update(classDict)
        return type.__new__(cls, name, bases, dct)

class Attr4(object):
    __metaclass__ = AttrMeta

print Attr4().func1(), Attr4().func2()
person Anurag Uniyal    schedule 15.02.2010
comment
Я думаю, что метод type - лучшее решение, учитывая этот вопрос. Это действительно требует от программиста реструктуризации остальной части определения атрибутов класса. С другой стороны, он избегает копаться в locals(), избегает определения настраиваемого метакласса и избегает искажения логики любых других используемых метаклассов. ИМО, это делает его приемлемым для библиотеки, которую другие будут использовать и в которую будут вносить свой вклад. - person AlanSE; 02.11.2017

Я долго боролся с этим, и мое возможное решение на примере (так как я новичок в кодировании):

names = ['Cuba I', 'San Felipe II Okeechobee', 'Bahamas', 'Cuba II', 'CubaBrownsville', 'Tampico', 'Labor Day', 
'New England', 'Carol', 'Janet', 'Carla', 'Hattie', 'Beulah', 'Camille', 'Edith', 'Anita', 'David', 'Allen', 
'Gilbert', 'Hugo', 'Andrew', 'Mitch', 'Isabel', 'Ivan', 'Emily', 'Katrina', 'Rita', 'Wilma', 'Dean', 'Felix', 
'Matthew', 'Irma', 'Maria', 'Michael']

for i in range(len(names)):
    namev                                      =                    names[i]
    locals()[''+str(namev.replace(' ',''))+''] =                  Hurricane(
        name                                   =                      namev)

Таким образом, «Куба I» будет «Кубой I» под классом «Ураган». Судя по моим исследованиям, проведенным другими разработчиками, это настоятельно не рекомендуется, потому что я еще не уверен. Похоже, что он отлично справился с поставленной задачей. В любом случае делайте с ним, что хотите.

person Franklin Gedaea    schedule 11.07.2020

person    schedule
comment
+1: Хорошо. Почему бы не создать новый класс стиля, унаследованный от object? - person S.Lott; 15.02.2010
comment
Это неподходящее место для этого. Это не только расточительно, но и существующие связанные методы будут отличаться от связанных методов от объектов, экземпляров которых будут созданы позже. Ну, больше, чем обычно. - person Ignacio Vazquez-Abrams; 15.02.2010