Python - 将Getter作为带参数的lambda

时间:2016-09-24 22:43:24

标签: python lambda

成为python的新手我刚刚遇到了property关键字,它基本上可以让你分配getter和setter。我想出了这个简单的例子

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)

现在在我的django项目中,我遇到过类似的东西(在属性中使用lambda)

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])

我不知道你可以在一个属性中使用lambda。现在从我的理解是它将profile的getter设置为lambda并且getter需要一个参数。这种困惑我。所以我决定尝试自己的例子

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 ? 

现在在我的情况下如何将参数传递给lambda?

2 个答案:

答案 0 :(得分:5)

编写属性的正常/自动方式是:

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而不是使用lambdas:

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)

我们无法将setter作为lambda传递,因为lambdas不能包含赋值。在这里,我继续使用self作为参数名称,但我可以使用任何变量名称,例如:

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

答案 1 :(得分: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>,这显然不是您想要的。

其次,getter不接受任何其他参数,因为......好吧,除了实例之外你真的不需要任何其他东西。

第三,我们也可以使用lambda作为制定者;我们在这里需要2个参数,实例和值,但lambda不能包含赋值,所以我们必须使用setattr()函数来解决它。

但如果这种方法不仅仅用于训练和探索,我建议使用@thebjorn所示的@property语法。