2014-12-30 5 views
-1

Хорошо, я перефразирую свой вопрос, поскольку моя мотивация недостаточно ясна.Свойства динамического питона

У нас есть класс, в котором пользователи будут заполняться свойствами, которые фактически реализованы с использованием более сложных механизмов хранения/поиска. Я упростил это ниже. Предположим, что механизм хранения только простой словарь сейчас:

class MyClass: 
    def __init__(self, d): 
     self.mydict = d 

    def getterX(self): 
     return self.mydict['X'] 
    def setterX(self, val): 
     self.mydict['X'] = val 
    X = property(getterX, setterX) 

    def getterY(self): 
     return self.mydict['Y'] 
    def setterY(self, val): 
     self.mydict['Y'] = val 
    Y = property(getterY, setterY) 

da = {} 
Ma = MyClass(da) 

Ma.X = 5 
Ma.Y = 6 
print(Ma.X, Ma.Y) #outputs 5 6 
print(da)   #outputs {'Y': 6, 'X': 5} 

Это работает отлично, за исключением его весьма подвержены ошибкам и многословным. Требуется пять строк не менее экземпляры X, которые необходимо вырезать + вставить для каждого нового объекта. Некоторые из этих классов могут иметь десятки свойств.

Вместо использования макросов (которые я не думаю, что Python поддерживает и неэффективно), я пытаюсь упростить это с некоторыми вспомогательными функциями:

da = {} 

class MyHelper: 
    def __init__(self, dict, label): 
     self.mydict = dict 
     self.mylabel = label 

    def getter2(self, other): 
     return self.mydict[self.mylabel] 

    def setter2(self, other, value): 
     self.mydict[self.mylabel] = value 

def makeProperty(d, label): 
    H = MyHelper(d, label) 
    return property(H.getter2, H.setter2) 

class MyClass: 
    def __init__(self, d): 
     self.mydict = d 

    X = makeProperty(da, 'X') #da is global, but should be self.mydict 
    Y = makeProperty(da, 'Y') # " " " 

Ma = MyClass(da) 

Ma.X = 5 
Ma.Y = 6 
print(Ma.X, Ma.Y) #outputs 5 6 
print(da)   #outputs {'Y': 6, 'X': 5} 

Сейчас этот почти работ, кроме вызовов makeProperty() необходимо получить доступ к глобальной переменной da, вместо использования данных о себе.

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

Надеюсь, это упростит ситуацию. Спасибо, Роб.

Дополнительная информация:

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

Итак, есть ли способ сделать эту работу, или пользователь отнесен к значительному разрезанию + вставке?

+2

Что именно вы должны быть? –

+0

Я не понимаю, что вы здесь делаете. Вы можете либо иметь сам класс, либо назначить ему переменные, либо присваивать переменные экземплярам класса. Я не могу думать, что это достигнет этого (потому что это не имеет смысла для меня). Возможно, если вы более подробно объясните, что именно вы пытаетесь достичь, я мог бы быть более полезным. –

+0

Свойство, которое, например, зеркалируется в общем хранилище. – rbairos

ответ

4

Учитывая вопрос «Могут ли экземпляры MyClass иметь уникальные функции getter/setter для свойства y?», Буквальный ответ «no» - дескрипторы (включая property) просматриваются классом, а не экземпляром ,

Однако дескрипторы уровня могут делегировать экземпляры вызываемых экземпляров, что приводит к аналогичному эффекту. Ваш пример не совсем понятно для меня, но, рассмотрим, например:

class Whatever(object): 

    def __init__(self, scale, getter=lambda x: 42): 
     self.scale = scale 
     self.getter = getter 

    @property 
    def y(self): 
     return self.getter(self.scale) 

plain = Whatever(33) 
fancy = Whatever(47, lambda x: x*2) 

plain.y Теперь будет 42, не обращая внимания plain.scale даже если это изменилось; тогда как fancy.y изначально будет 94, но изменение если и когда fancy.scale меняется. Это то, что вы пытаетесь сделать? Это наверняка поможет увидеть желаемые варианты использования ...

Добавлено: учитывая, что мы видели упрощенный вариант использования в большом редактируют добротности, вот как я бы решить:

class MyHelper: 
    def __init__(self, label): 
     self.mylabel = label 

    def getter2(self, other): 
     return other.mydict[self.mylabel] 

    def setter2(self, other, value): 
     other.mydict[self.mylabel] = value 

def makeProperty(label): 
    H = MyHelper(label) 
    return property(H.getter2, H.setter2) 

class MyClass: 
    def __init__(self, d): 
     self.mydict = d 

    X = makeProperty('X') 
    Y = makeProperty('Y') 

Завод-функция makeProperty может быть опущены, изменив имена MyHelper: __get__ и __set__ (т. Е. Сам по себе MyHelper) и вызывающий MyHelper непосредственно для создания своих экземпляров, которые должны быть назначены, но этот немного менее прямой подход может быть легче понять, поскольку он полагается на хорошо известный подход, известный встроенный тип property.

+0

Привет, я полностью перефразировал свой вопрос полностью для ясности. Я не уверен, что ваша информация по-прежнему применима. Спасибо за ваш вклад. – rbairos

+0

Да, мне пришло в голову это утро, мне не нужно было сдавать себя в makeProperty, так как он был бы доступен как «другой» аргумент в вызовах getter/setter. Благодарим вас за подтверждение и предоставление дополнительных объяснений. – rbairos

Смежные вопросы