2016-09-24 2 views
1

Будучи новым для python, я просто наткнулся на ключевое слово property, которое в основном позволяет назначать геттеры и сеттеры. Я придумал этот простой примерPython - свойство Getter как лямбда с параметром

class foo: 
    def __init__(self,var=2): 
     self.var= var 

    def setValue(self,var): 
     print("Setting value called") 
     self._var = var 

    def getValue(self): 
     print("getting value") 

    var = property(getValue,setValue) 

Сейчас в моем Джанго проекте я наткнулся на что-то вроде этого (с помощью лямбда в свойстве)

class UserProfile(models.Model): 
    user = models.OneToOneField(User) 
    likes_cheese = models.BooleanField(default=True) 
    puppy_name = models.CharField(max_length=20) 

User.profile = property(lambda u : UserProfile.objects.get_or_create(user=u)[0]) 

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

class double: 
    def setValue(self,var): 
     print("Setting value called") 
     self._var = var 

    def getValue(self): 
     print("getting value") 

    #var = property(getValue,setValue) 
    var = property(lambda x: print("The value of parameter is" + str(x))) 

d =double() 
d.var #Call the getter but how do i pass a value parameter to it ? 

Теперь, в моем случае, как я могу передать параметр лямбда?

+1

Значение первого параметра - 'self' .. – thebjorn

+0

Можете ли вы это объяснить. Я все еще немного смущен –

+0

Я добавил объяснение в качестве ответа. – thebjorn

ответ

5

Нормальный/idomatic способ написать свойство является:

class MyClass(object): 
    def __init__(self): 
     self._foo = 42 

    @property 
    def foo(self): 
     return self._foo 

    @foo.setter 
    def foo(self, val): 
     self._foo = val 

, как вы можете видеть, как и все другие определения методов в Python, первый параметр метода self.

Вы можете указать параметр, который вы хотите (не надо!), Но первым параметром всегда будет сам объект.

Приятный синтаксис выше, может быть деконструкции в

class MyClass(object): 
    def __init__(self): 
     self._foo = 42 

    def foo_get(self): 
     return self._foo 

    def foo_set(self, val): 
     self._foo = val 

    foo = property(foo_get, foo_set) 

и вместо передачи функции имен к property мы можем использовать вместо лямбды:

class MyClass(object): 
    def __init__(self): 
     self._foo = 42 

    def foo_set(self, val): 
     self._foo = val 

    foo = property(lambda self: self._foo, foo_set) 

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

foo = property(lambda u: u._foo, foo_set) 
+0

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

+0

Мы действительно можем использовать лямбда в качестве сеттера, мы можем заставить его работать без назначения. :) –

+1

Это не должно быть целью само по себе использовать здесь лямбда. Пример Django создает свойство вне класса (т. Е. После определения класса), а использование лямбда в этом случае предотвращает загрязнение пространства имен модулей. Люди чаще всего привыкли видеть свойства, написанные, как в моем первом примере, хотя, поэтому я бы предложил следующее стадо (если у вас нет веских причин не ... ;-) – thebjorn

1

Вы, вероятно, хотите сделать что-то вроде этого.

class double: 
    def __init__(self): 
     self._var = None 

    var = property(lambda self: self._var, 
        lambda self, value: setattr(self, "_var", value)) 

d = double() 
d.var = 3 
print(d.var) 

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

var = property(lambda x: print("The value of parameter is" + str(x))) 

x указывает на экземпляр, и str(x) нечто вроде <__main__.double object at 0x105f47a90>, что явно не то, что вы хотите.

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

В-третьих, мы также можем использовать лямбду в качестве сеттера; нам нужны 2 параметра здесь, экземпляр и значение, но лямбда не может содержать назначение, поэтому мы должны обходиться с функцией setattr().

Но если этот подход используется не только для обучения и изучения, я бы рекомендовал вернуться к синтаксису @property, как показано в статье @thebjorn.

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