Принудителен декоратор да разшири статичното поле върху наследен клас само дори ако не е изрично заменено

Работя върху писането на декоратор за използване в наследен клас и този декоратор трябва да добави някои стойности към списък, който е поле в базов клас. Проблемът, който открих, е, че освен ако тази дефиниция на клас изрично не изброява това поле, декораторът в крайна сметка променя базовия клас вместо това, което от своя страна добавя стойностите към всички останали класове, които също наследяват от този клас. Изглежда сякаш полетата не се дефинират в класа, а вместо това манипулират полетата в основния клас. Има ли начин да принудите наследените класове да имат свои собствени променливи полета (които започват със същата стойност като базовите полета), които не влияят на стойността на полетата на основния клас?

Със сигурност мога да намеря начини да заобиколя това, като не правя това, което правя, но се чудя дали има начин да накарам това, което искам да направя, да работи, за предпочитане чрез модифициране на декоратора. В допълнение към решението, обяснение защо е така и какво не разбирам за Python, наследяването на статични полета и декораторите би било страхотно!

По-долу съм дал основни случаи. Имайте предвид, че редовете това се отпечатва са, ако класовете Extension# се използват поотделно, а не един до друг, както са показани.

def add_values(cls):
    cls.my_list.append(1)
    return cls

class Base(object):
    my_list = []

### in the following case, the definition of Base actually changes
@add_values
class Extension1(Base):

    def append_1(self):
        self.my_list.append(1)
        print(self.my_list) ### this prints [1, 1]
        print(Base.my_list) ### this prints [1, 1]


### in this case, the definition of Base is fine and it only modifies
### the field on this class definition, which is what I'd expect.
@add_values
class Extension2(Base):
    my_list = []

    def append_1(self):
        self.my_list.append(1)
        print(self.my_list) ### this prints [1, 1]
        print(Base.my_list) ### this prints []

person RutledgePaulV    schedule 04.10.2014    source източник


Отговори (1)


Класовете не правят копия на стойности, които са наследили от базовите си класове. Това е само системата за търсене на атрибути, която търси, за да ги намери там, където са били дефинирани преди това. Това, което вероятно трябва да направите, е да промените мутацията на променливата на класа my_list в немутираща версия:

def add_values(cls):
    cls.my_list = cls.my_list + [1]  # like cls.my_list.append(1), but makes a new list
    return cls

Това създава нов списък с добавено 1 и го свързва към add_values, независимо дали декорирате базовия клас или производен.

person Blckknght    schedule 04.10.2014