Domanda Risolto Settare attributi ad una classe con setattr Python

jr_sottomajor

Utente Silver
2 Luglio 2017
96
33
4
79
Salve a tutti, stavo svolgendo questo esercizio:
decorator classe.png


Il mio codice è questo:
Python:
def classeBase(classe):
    setattr(classe, 'varC', 1000)
    setattr(classe, 'varl', 10)
    def f(self, v):
        print(v * self.varl)

    def g(x):
        print(x * classe.varC)
    setattr(classe, 'f', f)
    setattr(classe, 'g', g)
    return classe

@classeBase
class A:
    pass

#test
a=A()
a.f(12)
print(a.varC, a.varl)
print(A.varC, A.varl)
A.g(13)

Funziona correttamente, se non fosse che varC e varl sembrano essere entrambe variabili di classe poichè sia eseguendo a.varC (e quindi usando l'istanza) sia eseguendo A.varC( quindi usando la classe) viene sempre stampato il risultato..quindi quando faccio setattr, io assegno una variabile di classe a quanto ho capito?
Allora mi chiedo in che modo possa settare una variabile di istanza dall'esterno senza che questa diventi di classe.
Inoltre non ho ben capito la parte in cui dice " inoltre quando vengono create le istanze di una classe derivata queste 'nascono' con lo stesso valore di varl settato da __init__ di classe Base".. Non ho ben capito il motivo della precisazione, per cui non capisco se l'esercizio l'ho svolto correttamente oppure no.. Grazie in anticipo
 
Penso che non sia proprio quello che ti chiede l'esercizio. ClasseBase ti viene fornito esternamente e non lo puoi modificare, tu devi definire un decoratore che, applicato ad una classe, simuli la derivazione. Ti propongo una roba del genere
Python:
class ClasseBase:
    varC = 1000  
    def __init__(self):
        self.varl = 10
    def f(self, v):
        print(v * self.varl)
    @staticmethod
    def g(x):
        print(x * varC)

def deriveBaseClass(cls):
    return type(cls.__name__, (ClasseBase, ), dict())

@deriveBaseClass
class Foo: 
    pass
 
Python:
def ClassBase(c):
    setattr(c, 'varC', 1000)
    def __init__(self):
        self.varl=10
    setattr(c, '__init__', __init__)

    def f(self, v):
        print(v*self.varl)
    setattr(c, 'f', f)

    def g(x):
        print(x*c.varC)

    setattr(c, 'g', staticmethod(g))

    return c

Si alla fine la soluzione corretta è questa.. anzichè fare una classe si fa un metodo in modo tale che le classi derivate non possano modificare i metodi e le variabili della classe base