Я программирую моделирование отдельных нейронов. Поэтому мне приходится обрабатывать множество параметров. Идея состоит в том, что у меня есть два класса: один для SingleParameter и набор параметров. Я использую свойство (), чтобы легко получить доступ к значению параметра и сделать код более читабельным. Это идеально подходит для параметра sinlge, но я не знаю, как реализовать его для коллекции, поскольку я хочу назвать свойство в Collection после SingleParameter. Вот пример:
class SingleParameter(object):
def __init__(self, name, default_value=0, unit='not specified'):
self.name = name
self.default_value = default_value
self.unit = unit
self.set(default_value)
def get(self):
return self._v
def set(self, value):
self._v = value
v = property(fget=get, fset=set, doc='value of parameter')
par1 = SingleParameter(name='par1', default_value=10, unit='mV')
par2 = SingleParameter(name='par2', default_value=20, unit='mA')
# par1 and par2 I can access perfectly via 'p1.v = ...'
# or get its value with 'p1.v'
class Collection(object):
def __init__(self):
self.dict = {}
def __getitem__(self, name):
return self.dict[name] # get the whole object
# to get the value instead:
# return self.dict[name].v
def add(self, parameter):
self.dict[parameter.name] = parameter
# now comes the part that I don't know how to implement with property():
# It shoule be something like
# self.__dict__[parameter.name] = property(...) ?
col = Collection()
col.add(par1)
col.add(par2)
col['par1'] # gives the whole object
# Now here is what I would like to get:
# col.par1 -> should result like col['par1'].v
# col.par1 = 5 -> should result like col['par1'].v = 5
Другие вопросы, которые я задаю, чтобы понять свойство ():






Посмотрите на встроенные функции getattr и setattr. Вы, вероятно, станете намного счастливее.
Свойства предназначены для динамической оценки атрибутов или для того, чтобы сделать их доступными только для чтения. Что вам нужно, так это настроить доступ к атрибутам. __getattr__ и __setattr__ отлично справляются с этим, а также есть __getattribute__, если __getattr__ недостаточно.
Подробнее см. Документы Python по настройке доступа к атрибутам.
хорошо, я реализовал это сейчас с помощью set- / getattr. см. ответ ниже!
Вы смотрели пакет черт? Похоже, что вы изобретаете колесо с помощью классов параметров. У черт также есть дополнительные функции, которые могут быть полезны для вашего типа приложения (кстати, я знаю человека, который с радостью использует черты в нейронном моделировании).
Большое спасибо. Однажды я наткнулся на черты характера, но не понял, для чего они нужны. Наверное, сейчас самое время еще раз взглянуть :-)!
Теперь я реализовал решение с помощью set- / getattr:
class Collection(object):
...
def __setattr__(self, name, value):
if 'dict' in self.__dict__:
if name in self.dict:
self[name].v = value
else:
self.__dict__[name] = value
def __getattr__(self, name):
return self[name].v
Есть одна вещь, которая мне совсем не нравится: атрибутов нет в __dict__. И если бы они у меня тоже были, у меня была бы копия ценности - что может быть опасно ...
ну тогда просто не кладите их туда. В любом случае это будет сложно сделать, поскольку вы переопределили setattr.
Не рекомендуется использовать встроенные имена типов для переменных. Попробуйте изменить имя атрибута dict на что-нибудь более понятное.
Наконец мне удалось реализовать классы с помощью property (). Большое спасибо за совет. Мне потребовалось немало времени, чтобы разобраться в этом, но я могу обещать вам, что это упражнение поможет вам лучше понять ООП питонов.
Я реализовал это также с помощью __getattr__ и __setattr__, но до сих пор не знаю преимуществ и недостатков решения-свойства. Но, кажется, стоит задать еще один вопрос. Свойства-решения кажутся совершенно чистыми.
Итак, вот код:
class SingleParameter(object):
def __init__(self, name, default_value=0, unit='not specified'):
self.name = name
self.default_value = default_value
self.unit = unit
self.set(default_value)
def get(*args):
self = args[0]
print "get(): "
print args
return self._v
def set(*args):
print "set(): "
print args
self = args[0]
value = args[-1]
self._v = value
v = property(fget=get, fset=set, doc='value of parameter')
class Collection(dict):
# inheriting from dict saves the methods: __getitem__ and __init__
def add(self, par):
self[par.name] = par
# Now here comes the tricky part.
# (Note: this property call the get() and set() methods with one
# more argument than the property of SingleParameter)
setattr(Collection, par.name,
property(fget=par.get, fset=par.set))
# Applying the classes:
par1 = SingleParameter(name='par1', default_value=10, unit='mV')
par2 = SingleParameter(name='par2', default_value=20, unit='mA')
col = Collection()
col.add(par1)
col.add(par2)
# Setting parameter values:
par1.v = 13
col.par1 = 14
# Getting parameter values:
par1.v
col.par1
# checking identity:
par1.v is col.par1
# to access the whole object:
col['par1']
Поскольку я новичок, я не знаю, как двигаться дальше: как относиться к уточняющим вопросам (например, к самому этому):
Другие вопросы, которые я задаю, чтобы понять свойство ():
Использование одних и тех же функций get / set для обоих классов вынуждает вас сделать уродливый взлом со списком аргументов. Очень схематично, вот как я бы это сделал:
В классе SingleParameter определите получение и установку как обычно:
def get(self):
return self._s
def set(self, value):
self._s = value
В классе Collection вы не можете узнать информацию до тех пор, пока не создадите свойство, поэтому вы определяете функцию метасета / метагета и конкретизируете их только позже с помощью лямбда-функции:
def metaget(self, par):
return par.s
def metaset(self, value, par):
par.s = value
def add(self, par):
self[par.name] = par
setattr(Collection, par.name,
property(
fget=lambda x : Collection.metaget(x, par),
fset=lambda x, y : Collection.metaset(x,y, par))
У меня есть класс, который делает что-то подобное, но в объекте коллекции я сделал следующее:
setattr (self, par.name, par.v)
когда я добавляю: ----- def setattr __ (self, name, value): self.dict [name] = value ---- Я получаю сообщение об ошибке, что «объект 'Collection' не имеет атрибута 'dict'» - хотя это реализовано в __init.