Показаны сообщения с ярлыком functions. Показать все сообщения
Показаны сообщения с ярлыком functions. Показать все сообщения

вторник, 29 апреля 2014 г.

Python: статические переменные в функциях

Реализация на классе

Самый прямой и дубовый путь в питоне для этого, это использовать атрибуты классов. Т.е. хранить состояние в атрибуте класса, в __init__() его инициализировать, а в вызовах методов делать с этим атрибутом то, что нам нужно.

Предположим, что мы хотим реализовать счетчик вызовов функции. Давайте напишем класс. Он будет не самым эффективным решением задачи, сразу предупреждаю, но решение классическое, дубовое, понятное и работающее.

1 class A():
 2 
 3     def __init__(self):
 4         self.cnt = 0
 5 
 6     def f(self):
 7         self.cnt += 1
 8         return self.cnt
 9 
10 a = A()
11 
12 print " Class A testing"
13 print a.f()
14 print a.f()
15 print a.f()
16 
17 > Class A testing
18 > 1
19 > 2
20 > 3

Реализация внутри функции

Предыдущий пример работает. Но есть и недостатки. Нужно определять класс, создавать его объект, вызвать метод объекта. А нельзя ли попроще, так, чтобы все было спрятано внутри функции и нам не нужно бы было заморачиваться с тем, что не относится собственно к нужному нам эффекту?

Можно!

В питоне все является объектом, в том числе и функция. И у функции могут быть атрибуты. Эти атрибуты могут создаваться во время выполнения и храниться все время, пока существует программа.

Попробуем реализовать следующий план, например для того же счетчика вызовов:

    Внутри функции создаем атрибут.
    При первом вызове присваиваем ему начальное значение.
    В следующих вызовах увеличиваем это значение на 1.

Код:
1 def f():
 2     try:
 3         f.a += 1
 4     except AttributeError:
 5         f.a = 0
 6     return f.a
 7 
 8 print " Function f() testing"
 9 print f()
10 print f()
11 print f()
12 
13 > Function f() testing
14 > 1
15 > 2
16 > 3
http://blog.swlogic.eu/2011/06/19/python-staticheskie-peremennyie-v-funktsiyah/ 

воскресенье, 27 апреля 2014 г.

Передача параметра по ссылке (изменение переменной внутри функции)

Если при вызове функции подставить в качестве значения аргумента переменную, а в теле функции мы меняем значение аргумента, то то, что произойдет, зависит от того, с каким значением связана наша переменная.

Если переменная связана с неизменяемым значением, например None, int, str, tulpe, ключи словарей, то естественно, это значение не изменится. А вот если переменная связана со списком, словарем или классом, то значение связанного с переменной объекта изменится.

Не изменяется:
1 def a(b):
 2     b = 2
 3 
 4 c = 3
 5 print c
 6 a(c)
 7 print c
 8 
 9 >>> 3
10 >>> 3
Изменяется:
 1 def a(b):
 2     b[0] = 2
 3 
 4 c = [3]
 5 print c
 6 a(c)
 7 print c
 8 
 9 >>> [3]
10 >>> [2]