2016-01-26 3 views
0

Я хочу, чтобы функция класса была в курсе self.var, независимо от того, изменяется ли она по его встроенному дочернему классу. Как класс С1 дочерний класс в P, и это изменяет значение УАК, тем FUNC делает A. Когда «вар» не меняется, как и C2, а затем сделать B.Метод Python должен знать, что self.variable изменен

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 к FULLFILL своей собственной функции:

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, некоторые из них нет. Я хочу, чтобы метод визуализации знал о имени шаблона, если он был изменен его дочерним элементом и соответствующим образом выполняет разные визуализации.

+5

Это звучит как проблема [XY] (https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Какова ваша цель _actual_? (I.e., почему вы пытаетесь это сделать?) Вероятно, это лучшее решение. – Chris

+0

Вы не можете использовать 'if self.var! =" Original ":'? – furas

+1

@ Крис, да, thx для ссылки на проблему XY, я обновляю свой quesiton. –

ответ

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 и использовать его в качестве родителя для классов C1 и C2. Затем мы можем использовать 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() 
+0

первое решение является блестящим, более простым и понятным. Почему вы говорите, что второй вариант более общий? –

+1

Второй будет работать, если '' var'' был атрибутом * экземпляра * родителя. Первый работает только тогда, когда '' var'' является атрибутом класса. – lextoumbourou

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__ непосредственно чувствует немного взломанный, это дает вам гибкий способ проверить изменения на любом количестве переменных класса.

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' 

Это позволяет определить разумную отправную точку, чтобы затем проверить на всякий раз, когда «вар» отменяется, но и разрешить кому-то, кто должно, чтобы они могли переопределить значение, в то же время настоятельно рекомендуя, чтобы они этого не сделали.

EDIT: Обновлено, так как методы и переменные класса с ведущим подчеркиванием защищены, два ведущих символа подчеркивания являются частными.