Python方法要注意self.variable已更改

时间:2016-01-26 02:23:31

标签: python class methods

我想让一个类函数知道self.var是否被它固有的子类改变了。就像C1类是P的子类一样,它改变了var的值,func改为A.当“var”没有改变时,就像C2一样,然后做B。

class P(object):
    var =  "original"

    def func(self):
        if # self.var is changed by child instance:
            do A
        else:
            do B

class C1(P):
    var = "changed"

class C2(P):
    pass

c1 = C1
c2 = C2

c1.func() # do B
c2.func() # do A

由于我这样做的原因和更复杂的解释。

我需要修改openstack地平线code来填补我自己的功能:

class TabGroup(html.HTMLElement):
    ......
    template_name = "horizon/common/_tab_group.html"
    ......
    def render(self):
        return render_to_string(self.template_name, {"tab_group": self})

TabGroup通常由其他子项继承,其中一些更改template_name,其中一些不是。我希望render方法在其子节点被其更改时知道template_name,并相应地执行不同的呈现。

3 个答案:

答案 0 :(得分:3)

由于var是一个类属性,您只需检查实例的值是否与父类不同:

class P(object):
    var = "original"

    def func(self):
        if self.var != P.var:
            print "DO A"
        else:
            print "DO B"

class C1(P):
    var = "changed"

class C2(P):
    pass

c1 = C1()
c2 = C2()

c1.func()  # Do A
c2.func()  # Do B

另一个更通用的选项可能是使用P方法定义func的子类,并将其用作C1C2类的父类。然后,我们可以使用super来访问父属性。如下:

class P(object):
    var = "original"

class PChild(P):
    def func(self):
        if self.var != super(PChild, self).var:
            print "DO A"
        else:
            print "DO B"

class C1(PChild):
    var = "changed"

class C2(PChild):
    pass

c1 = C1()
c2 = C2()

c1.func()
c2.func()

答案 1 :(得分:2)

要告知类的属性何时更改,请使用__setattr__魔术方法。以下是您在课堂上使用它的方法:

class AttributeCatcher(object):

    def __init__(self):
        # to declare without __setattr__ firing we put it directly into self.__dict__
        self.__dict__['whatever'] = 'spam'

    def __setattr__(self, name, value):
        self.__dict__[name] = value
        print('{} changed to {}'.format(name, value))


a = AttributeCatcher()
a.whatever = 'eggs'
# outputs "whatever changed to eggs"

从那里开始,创建set以存储更改并不是一件容易的事:

class AttributeCatcher(object):

    def __init__(self):
        self.__dict__['whatever'] = 'spam'
        self.__dict__['changes'] = set()

    def __setattr__(self, name, value):
        self.__dict__[name] = value
        self.__dict__['changes'].add(name)

    def func(self):
        if 'whatever' in self.changes:
            print('DO A')
        else:
            print('DO B')

a = AttributeCatcher()
a.whatever = 'eggs'
a.func() #outputs "DO A"

b = AttributeCatcher()
b.func() #outputs "DO B"

虽然直接把事情放到self.__dict__会让人感觉有点笨拙,但这可以让你灵活地检查任何数量的类变量的变化。

答案 2 :(得分:1)

我认为最简单的解决方案是在类上定义一个私有变量,然后检查该值是否相同(实际上没有受到保护):

class P(object):
    __private = "original"
    var =  __private

    def func(self):
        if self.var == self.__private:
            do A
        else:
            do B

现在,这允许人们在需要时更改__private变量,但是从类外部访问它意味着它将按如下方式访问:

>>> P._P__private
'original'
>>> P._P__private = 'newvalue'

这允许您定义一个合理的起点,然后在“var”被覆盖时检查,但也允许需要的人可以覆盖该值,同时强烈建议他们不要

编辑:更新,因为带有前导下划线的方法和类变量受到保护,两个前导下划线是私有的。