Grundlæggende metode kæde

Jeg fandt denne metode kæde i python, men selv med det kunne jeg ikke forstå, metode kæde i Python.

Her de mål, der er to: løse kodning problem og forstår metode sammenkædning (i betragtning af at jeg stadig ikke er 100% sikker med callables).

Ned til definitionen af problemet.

Jeg ønsker en klasse, der har to metoder: man sætter en parameter af objektet = ‘line’ og andre gange ‘bar’.

Dette er hvad jeg har fået så langt:

class foo():
    def __init__(self, kind=None):
        self.kind = kind

    def __call__(self, kind=None):
        return foo(kind=kind)

    def my_print(self):
        print (self.kind)

    def line(self):
        return self(kind='line')
    def bar(self):
        return self(kind='bar')

Desværre, med denne kode for at jeg kan opnå mit mål at gøre dette

a = foo()
a.bar().line().bar().bar().line().my_print()

Men jeg vil gerne opnå det samme resultat ved at skrive denne kode

a = foo()
a.bar.line.bar.bar.line.my_print()

Hvordan kan jeg opnå det? Jeg tror der er noget galt i, hvordan jeg har defineret __call__ metode. På forhånd tak for din hjælp.

OriginalForfatteren Pezze | 2017-01-23

2 svar

  1. 39

    Metode kæde er simpelthen blive i stand til at tilføje .second_func() til, hvad .first_func() afkast. Det er forholdsvis let gennemføres ved at sikre, at alle omstillelig metoder vende tilbage self. (Bemærk, at dette har intet at gøre med __call()__).

    class foo():
        def __init__(self, kind=None):
            self.kind = kind
        def my_print(self):
            print (self.kind)
            return self
        def line(self):
            self.kind = 'line'
            return self
        def bar(self):
            self.kind='bar'
            return self

    Du kan bruge foo objekter i en ikke-lænket måde ved at ignorere deres returnerede værdier:

    a = foo()
    a.line()
    a.my_print()
    a.bar()
    a.my_print()
    
    assert a.kind == 'bar'

    Eller, da hver funktion returnerer nu objektet selv, kan du betjene
    direkte på den returnerede værdi. Du kan bruge metoden kæde med dette tilsvarende kode:

    b = foo()
    b.line().my_print().bar().my_print()
    assert b.kind == 'bar'

    Eller endda:

    c = foo().line().my_print().bar().my_print()
    assert c.kind == 'bar'

    Spørgsmålet om at slippe af med den () ringer syntaks er en helt separat koncept fra metode kæde. Hvis du vil kæde egenskaber, og har disse ejendomme mutere deres objekt, skal du bruge @property dekoratør. (Men muterer objekter via en ejendom, der synes farlige. Bedre at bruge en metode og et navn, er det med et verbum: .set_line() i stedet for .line, for eksempel.)

    class foo():
        def __init__(self, kind=None):
            self.kind = kind
        def my_print(self):
            print (self.kind)
            return self
        @property
        def line(self):
            self.kind = 'line'
            return self
        @property
        def bar(self):
            self.kind='bar'
            return self
    
    a = foo()
    a.line
    a.my_print()
    a.bar
    a.my_print()
    
    assert a.kind == 'bar'
    
    b = foo()
    b.line.my_print().bar.my_print()
    assert b.kind == 'bar'
    
    c = foo().line.my_print().bar.my_print()
    assert c.kind == 'bar'
    Tak for den meget udtømmende svar!!

    OriginalForfatteren Robᵩ

  2. 3

    Bruge egenskaber (descriptors).

    class foo:
        def __init__(self, kind=None):
            self.kind = kind
    
        def __call__(self, kind=None):
            return foo(kind=kind)
    
        def my_print(self):
            print (self.kind)
    
        @property
        def line(self):
            return self(kind='line')
    
        @property
        def bar(self):
            return self(kind='bar')

    Bemærk dog, at du overskrive noget, ændring virker ikke inplace (som nok er godt, btw). Anyway, dette ligner ikke et godt design valg for de fleste i den virkelige verden tilfælde, fordi der på et tidspunkt metoder vil kræve argumenter.

    OriginalForfatteren Eli Korvigo

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *