2013-06-09 19 views
11

Zastanawiam się przez chwilę, czy istnieje łatwiejszy sposób przypisania atrybutów klas do metody lokalnej przestrzeni nazw. Na przykład, w dosomething metody, ja wyraźnie odwołują się do self.a i self.b:Python importuje atrybuty klas do metody lokalnej przestrzeni nazw

class test: 
    def __init__(self): 
     self.a = 10 
     self.b = 20 

    def dosomething(self): 
     a = self.a 
     b = self.b 
     return(a + b) 

Ale czasami mam wiele zmiennych (ponad 10) i robi się bałagan na rodzaj i patrzeć - Chciałbym mieć kilka instrukcji var = self.var na początku metody.

Czy istnieje sposób na bardziej kompaktowy sposób? (Wiem aktualizowania local() nie jest dobrym pomysłem)

Edycja: Najlepiej, co chcę jest:

def dosomething(self): 
    populate_local_namespace('a', 'b') 
    return(a + b) 
+0

Dlaczego próbujesz to zrobić w pierwszej kolejności?Co jest złego w przypadku jednoliniowej metody "dosomething", która wygląda jak "return (self.a + self.b)"? Jaką korzyść z tego możesz się spodziewać? – rmunn

+3

Mam swoje powody - szczególnie, że wykonuję skomplikowane obliczenia i wiele wyrażeń "self" jest bardzo długich i brzydkich. – joon

Odpowiedz

21

Q. Czy istnieje jakiś sposób, aby to zrobić bardziej zwarty sposób?

1. Jeśli zmienne są tylko do odczytu, byłoby rozsądnie pythonowy czynnik out wielo-zmiennej metody dostępowej:

class Test: 

    def __init__(self): 
     self.a = 10 
     self.b = 20 
     self.c = 30 

    def _read_vars(self): 
     return self.a, self.b, self.c 

    def dosomething(self): 
     a, b, c = self._read_vars() 
     return a + b * c 

    def dosomethingelse(self): 
     a, b, c = self._read_vars() 
     return a - b * c 

Jeśli zmienne nie są tylko do odczytu , najlepiej trzymać się z self.inst_var = value. Jest to normalny sposób pisania kodu w Pythonie i zwykle jest to, czego większość ludzi się spodziewa.


2. Raz na jakiś czas można zobaczyć ludzi skracać self z krótszą nazwą zmiennej. Jest on stosowany, gdy korzyści czytelności decluttering przewyższają koszty czytelność przy użyciu niestandardowego nazwę zmiennej:

def updatesomethings(s): 
    s.a, s.b, s.c = s.a + s.c, s.b - s.a, s.c * s.b 

3. Innym sposobem obsłużyć bardzo dużą ilość zmiennej instancji jest je przechowywać zmienny w pojemniku na łatwość pakowania i rozpakowywania:

class Test: 

    def __init__(self, a, b, c, d, e, f, g, h, i): 
     self._vars = [a, b, c, d, e, f, g, h, i] 

    def fancy_stuff(self): 
     a, b, c, d, e, f, g, h, i = self._vars 
     a += d * h - g 
     b -= e * f - c 
     g = a + b - i 
     self._vars[:] = a, b, c, d, e, f, g, h, i 

4. Istnieje ja s również słownik podejście manipulacja, że ​​będzie działać, ale ma zapach kodu, że większość Pythonistas by unikać:

def updatesomethings(self): 
    a = 100 
    b = 200 
    c = 300 
    vars(self).update(locals()) 
    del self.self 
+0

Dzięki. Właściwie to właśnie robiłem. Ale nie jest to wystarczająco elastyczne, ponieważ kiedy chcę zmienić zmienne, muszę zmienić oba miejsca. Byłoby wspaniale, gdyby istniał sposób, w którym mogę po prostu przekazać nazwę atrybutu do funkcji jako łańcucha znaków, a atrybut staje się zmienną lokalną. – joon

+0

@joon Dodałem również kilka innych opcji. –

+0

Tak 4 wygląda przerażająco :) Chciałbym tylko użyć funkcji wywoływania funkcji ('_read_vars()') na teraz. Bardzo dziękuję za Twoją pomoc!! – joon

-2

można łatwo rozwiązać ten problem kompromis, poprzez przechowywanie zmiennych w słowniku.

data = {} 
copy_to_local_variables = ["a", "b", "c", "d"] 
for var_name in copy_to_local_variables: 
    data[var_name] = getattr(self, var_name) 

(choć jestem w stanie zrozumieć, dlaczego trzeba skopiować atrybuty klasy z metodą lokalnej przestrzeni nazw)

+1

Czy nie zrobi to po prostu dicta o nazwie "data" z tymi zmiennymi zamiast tworzenia zmiennych lokalnych odnoszących się do atrybutów klas? Nie sądzę, że tego chcę. – joon

-2

znalazłem inny sposób:

def dosomething(self): 
    for key in ['a', 'b']: 
     exec('{} = self.{}'.format(key, key)) 

    return(a + b) 

ja nie wiem, czy to jest niebezpieczne albo nie. Byłoby wspaniale, gdyby ktoś mógł to skomentować.

+3

Byłoby niebezpieczne, gdyby klucz był kiedykolwiek łańcuchem pochodzącym z niezaufanego źródła. – korylprince

+2

Prawdopodobnie jest również bardzo powolny, ponieważ za każdym razem, gdy wywoływane jest wywołanie exec(), Python musi lex, parsować, kompilować i wykonywać zupełnie nową instrukcję tak, jakby widział ją po raz pierwszy. –

+0

Dzięki za komentarze! – joon

Powiązane problemy