Șablon de clasă pentru începători (Revizuirea codului, Python, Orientat Pe Obiecte, Python 2.X)

tlebrize a intrebat.

Vreau să permit oricui care nu a codat niciodată să facă clase în funcție de șablonul meu cu puține sau deloc cunoștințe de Python.

Aceste clase trebuie să facă 2 lucruri:

  • Să moștenească de la alte clase similare lor.
  • Să conțină variabile, actualizând valorile dacă acestea au fost modificate sau păstrându-le dacă nu.

De dragul simplității, nu vreau să am super() pe aceste clase noi, deoarece încerc să nu sperii noii veniți cu lucruri pe care nu le pot înțelege încă. Iată cum am procedat:

class Template(object):

    def __init__(self):
        self.value = "hello"
        self.other_value = "bonjour"
        self.constant_value = 42
        current_class = self.__class__
        inits = []
        while (current_class.__name__ != "Template"):
            inits.append(current_class.init)
            current_class = current_class.__bases__[0]
        for i in reversed(inits):
            i(self)

    def init(self):
        pass

    def info(self):
        print self.value
        print self.other_value
        print self.constant_value
        print ""

class Deep(Template):
    def init(self):
        self.value = "howdy"
        self.other_value = "salut"

class Deeep(Deep):
    def init(self):
        self.value = "hi"

class Deeeep(Deeep):
    def init(self):
        self.value = "'sup"

very_deep = Deeeep()
not_so_deep = Deep()
very_deep.info()
not_so_deep.info()

Aceste ieșiri :

sup
salut
42

howdy
salut
42

Ceea ce este exact ceea ce vreau, dar arată foarte ciudat, ofuscat și ne-pitic. Aveți vreo idee de îmbunătățire?

Comentarii

  • Ați putea să explicați puțin mai bine cum ar trebui să folosească un novice Template clasa? Ar trebui să își creeze propriile clase care să moștenească din Template, , sau ar trebui să facă pur și simplu o copie a codului și să îl modifice în funcție de nevoile lor? În ambele cazuri, nu înțeleg cum acest lucru va fi mai ușor pentru ei decât să învețe să scrie propria clasă care să facă ceea ce au nevoie.  > Por mkrieger1.
  • Rezultatul ar trebui să fie de fapt 'sup, , nu sup. Acest lucru a fost schimbat din greșeală în rev. 2, dar nu pot să îl repar pentru că este vorba doar de o editare cu un singur caracter.-  > Por mkrieger1.
2 răspunsuri
301_Moved_Permanently

În loc să gestionați singur ierarhia claselor, ar trebui să vă bazați pe modul standardizat de Python de a face acest lucru: MRO. Puteți ajunge la fiecare clasă din ierarhie folosind-o fără a cădea în capcana de a uita unele atunci când aveți de-a face cu moștenirea multiplă (ceea ce codul dvs. face):

class Template(object):
    def __init__(self):
        self.value = "hello"
        self.other_value = "bonjour"
        self.constant_value = 42

        for cls in reversed(self.__class__.mro()):
            if hasattr(cls, 'init'):
                cls.init(self)

Cu toate acestea, dacă planul dvs. este de a face suport pentru apelul de super() pe init fără ca utilizatorul să o apeleze în mod explicit, v-aș sfătui să puneți chestiunile de inițializare în init de asemenea:

class Template(object):
    def __init__(self):
        for cls in reversed(self.__class__.mro()):
            if hasattr(cls, 'init'):
                cls.init(self)

    def init(self):
        self.value = "hello"
        self.other_value = "bonjour"
        self.constant_value = 42

Simon

Aceasta:

...
while (current_class.__name__ != "Template"):
...

este ciudat. Fă așa:

...
while current_class != Template:
...

face același lucru, doar că compară clasele în loc de șiruri de caractere.


Și acest lucru este ciudat:

for i in reversed(inits):
     i(self)

i este folosit pentru iterație, așa că devine obscur, dar tu apelezi un int? Aceasta:

for init in reversed(inits):
    init(self)

este mai explicativă.


Nu prea știu ce să zic despre următoarea parte, dar ați putea defini un mic lambda

extract_first = lambda x: x[0]

cu un nume explicativ, lăsând acea parte a codului ca aceasta:

extract_first = lambda x: x[0]

while current_class != Template:
    inits.append(current_class.init)
    current_class = extract_first(current_class.__bases__)
for init in reversed(inits):
    init(self)

Se lasă cu mai multe cuvinte și text, dar cu mai puțin jargon de programare. Ar putea fi bun.


Acum, ceea ce aș face eu dacă ar fi pentru cineva nou în programare este să mă redau pe altceva, apoi abstractizarea de la init și să abstractizez în ceva de genul biologiei:

class Exists(object):
    perceptible = True


class Alive(Exists):
    can_use_sustenance = True


class Vertebrate(Alive):
    can_move = True


class Mammal(Vertebrate):
    heat_generation = True


class Dog(Mammal):
    pass


class Cat(Mammal):
    pass

Testat pe celălalt semnificativ al meu 🙂