Dostęp do zmiennej funkcji poza funkcją bez użycia "global"

Próbuję uzyskać dostęp do lokalnej zmiennej funkcji poza funkcją w Pythonie. Na przykład

bye = ''
def hi():
    global bye
    something
    something
    bye = 5
    sigh = 10

hi()
print bye

Powyższe działa dobrze, jak powinno. Ponieważ chcę dowiedzieć się, Czy Mogę uzyskać dostęp do bye Poza hi() bez użycia global bye, próbowałem:

def hi():
    something
    something
    bye = 5 
    sigh = 10
    return

hi()
x = hi()
print x.bye 

Powyższe daje AttributeError: 'NoneType' object has no attribute 'bye'.

Potem próbowałem:

def hi():
    something
    something
    bye = 5
    sigh = 10
    return bye 
hi()
x = hi()
print x.bye

Tym razem nie daje nawet błędu.

Czy istnieje sposób dostępu do lokalnej zmiennej funkcji (bye) poza jej funkcją (hi()) bez użycia globali i bez drukowania zmiennej sigh również? (Pytanie zostało edytowane, aby dołączyć sigh po komentarzu @ hcwhsa poniżej.

Author: martineau, 2013-10-11

5 answers

Możesz zrobić coś w tym stylu (co działało zarówno w Pythonie v2.7.17, jak i v3. 8. 1, Kiedy go testowałem):

def hi():
    # other code...
    hi.bye = 42  # Create function attribute.
    sigh = 10

hi()
print(hi.bye)  # -> 42

Funkcje są obiektami w Pythonie i mogą mieć przypisane dowolne atrybuty.

Jeśli masz zamiar robić tego typu rzeczy często, możesz zaimplementować coś bardziej ogólnego, tworząc dekorator funkcji, który dodaje argument this do każdego wywołania dekorowanej funkcji.

Ten dodatkowy argument da funkcjom sposób na odwołują się do siebie bez konieczności jawnego osadzania (hardcode) ich nazwy w pozostałej części definicji i jest podobna do argumentu instancji, który metody klasy automatycznie otrzymują jako pierwszy argument, który zwykle nazywa się self - wybrałem coś innego, aby uniknąć nieporozumień, ale podobnie jak argument self, może być nazwany, jak chcesz.

Oto przykład takiego podejścia:
def add_this_arg(func):
    def wrapped(*args, **kwargs):
        return func(wrapped, *args, **kwargs)
    return wrapped

@add_this_arg
def hi(this, that):
    # other code...
    this.bye = 2 * that  # Create function attribute.
    sigh = 10

hi(21)
print(hi.bye)  # -> 42

Uwaga

To nie działa jak pokazano dla metod klasowych. Zobacz też atrybuty funkcji gdy w klasie .

 106
Author: martineau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-25 00:02:12

Problem polega na tym, że wywoływałeś print x. pa po ustawieniu X jako string. Po uruchomieniu x = hi() uruchamia hi () i ustawia wartość x na 5 (wartość bye; nie ustawia wartości x jako odniesienia do samej zmiennej bye). EX: bye = 5; x = bye; bye = 4; print x; drukuje 5, nie 4

Ponadto, nie musisz uruchamiać hi() dwa razy, po prostu uruchom x = hi(), a nie hi();x=hi() (tak jak to było uruchomione hi (), nie robiąc nic z wynikową wartością 5, a następnie ponownie uruchom tę samą hi () i zapisując wartość 5 do X zmienna.

Więc Pełny kod powinien być

def hi():
    something
    something
    bye = 5
    return bye 
x = hi()
print x

Jeśli chcesz zwrócić wiele zmiennych, jedną z opcji byłoby użycie listy lub słownika, w zależności od tego, czego potrzebujesz.

Ex:

def hi():
    something
    xyz = { 'bye': 7, 'foobar': 8}
    return xyz
x = hi()
print x['bye']

Więcej o słownikach Pythona w http://docs.python.org/2/tutorial/datastructures.html#dictionaries

 9
Author: John,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-11 20:04:21

Doświadczyłem tego samego problemu. Jedna z odpowiedzi na twoje pytanie doprowadziła mnie do następującego pomysłu (który w końcu zadziałał). Używam Pythona 3.7.

    # just an example 
    def func(): # define a function
       func.y = 4 # here y is a local variable, which I want to access; func.y defines 
                  # a method for my example function which will allow me to access 
                  # function's local variable y
       x = func.y + 8 # this is the main task for the function: what it should do
       return x

    func() # now I'm calling the function
    a = func.y # I put it's local variable into my new variable
    print(a) # and print my new variable

Następnie uruchamiam ten program w Windows PowerShell i otrzymuję odpowiedź 4. Wniosek: aby uzyskać dostęp do zmiennej lokalnej funkcji, można dodać nazwę funkcji i kropkę przed nazwą zmiennej lokalnej (a następnie, oczywiście, użyć tej konstrukcji do wywołania zmiennej zarówno w ciele funkcji, jak i poza nim). Mam nadzieję, że to pomoże.

 3
Author: Ivan Nepomnyashchikh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-23 16:02:00

Mógłbyś zrobić coś w tym stylu:

def static_example():
   if not hasattr(static_example, "static_var"):
       static_example.static_var = 0
   static_example.static_var += 1
   return static_example.static_var

print static_example()
print static_example()
print static_example()
 1
Author: Thomas Corll,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-16 21:41:19
 def hi():
     bye = 5
     return bye  

print hi()
 1
Author: Allan Mwesigwa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-10 09:04:49