Так как это раздел для новичков я решил выложить немножко интересных и даже захватывающих материалов, полезных в основном для людей мало знакомых с программированием но желающих научиться. Я пишу статью по программированию в первый раз и не претендую на точность изложения, однако некоторым моим знакомым эта статья помогла понять зачем им вообще использовать декораторы.
Декоратор - простой способ изменения поведения функции или класса. Это один из самых непонятных элементов языка Python, который на самом деле не отличается особой сложностью.
1 - Зачем нужны декораторы?
Декоратор это очень простой способ изменить поведение вашей функции или класса, с помощью них можно конструировать потоки, измерять время выполнений функции. Декоратор может стать оказаться инструментом при оптимизации программы, для синхронизации потоков, для проверки условий.
2 - Синтаксис
@*Function_Name(arguments)*
def *Other_Function_name*(*Some_arguments*) : *code*
def *Other_Function_name*(*Some_arguments*) : *code*
*Function_Name* = *Other_Function_name*(*Function_Name*)
Причем выполнив код один раз, функции навсегда(Ну, по крайней мере, на время выполнения программы или переопределения функции) будет присвоено такое значение.
def empty(f):
return None
@empty
def function(x):
return x
def empty(f):
return None
def function(x):
return x
function = empty(function)
print function
И теперь каждый раз вызывая функцию function результатом будет None, если вы не переопределяете значение, например как в коде, указанном ниже.
def sqr(f): return 10
def function(func):
@func
def summ(x): return x-0.1*x
print summ
Типичный пример использования декораторов - функция засекающая время выполнения другой функции.
Эта функция будет получать декорируемую ею функцию и список её аргументов, после чего засекать время выполнения, очень похоже на использование тегов, то есть сначала записывается текущее время, затем выполняется функция а затем записывается разность между текущим временем и ранее записанным
import time
def Timer(f): # Функция таймер, в которую будет "обернута" будущая функция
def func(*args, **kwargs): # Функция которая будет выполнять переданную таймеру функцию и засекать время, требуется для того
# чтоб выполнялась функция с произвольными начальными данными
currtime = time.time() # Запомнить текущее время
result = f(*args'''Кортеж аргументов''', **kwargs'''Словарь аргументов''') #Выполнить введенную в таймер функцию
print "Time to function : %f" % (time.time()-currtime) # Вывести результат
return result
return func # Вернуть функцию
@Timer
def Euclid(x, y):
while x != y:
if x > y:
x = x - y
else:
y = y - x
return x
print Euclid(216,6)
# напечатает 'Время выполнения: *время выполнения вашей функции*'
Но на выполнение функции Timer также требуется время, как гласит экспериментальная физика “Каждый наблюдаемый опыт не точен, вследствии влияния наблюдателя”
Можно написать код по-другому, учтя неточность.
import time
def Timer(f): # таймер выполнения
def func(*args, **kwargs): #Функция, позволяющая принимать произвольные аргументы
currtime = time.time() #Запись текущего времени
result = f(*args, **kwargs) #Выполнение функции заданной на вход
s = time.time()-currtime #Разность текущего времени и ранее записанного
return s #Вернуть время выполнения
return func
@Timer
def Euclid( x =12, y =144):
while x != y:
if x > y:
x = x - y
else:
y = y - x
return x
@Timer
def empty():return None
print '%1.15f' % (Euclid(5673, 100) - empty()) #Разность между временем выполнения пустой функции и функции Euclid
import time
def Timer(f):
def func(*args, **kwargs):
currtime = time.time()
result = f(*args, **kwargs)
s = time.time()-currtime
return s
return func
def Euclid( x =12, y =144):
while x != y:
if x > y:
x = x - y
else:
y = y - x
return x
def empty():return None
Euclid = Timer(Euclid)
empty = Timer(empty)
print '%1.15f' % (Euclid(5673, 100) - empty())
@n-th
…
@third
@second
@first
4 - Применение декораторов
Декораторам можно передавать параметры.
То есть декоратором будет являться результат выполнения введенной функции-декоратора.
@function(*value*)
def otherFunction : *code*
это тоже самое что выражение вида
def otherFunction : *code*
otherFunction = function(*value*)(otherFunction)
def state(t):
def Start(f):
def imfunc(*args, **kwargs):
result = 1
for i in xrange(t):
result = result*f(*args, **kwargs)
return result
return imfunc
return Start
def start():
while 1:
try:
m = int(raw_input('Input number :'))
break
except ValueError:
print 'This is not value'
@state(m)
def func(x):
return x
print func(m)
start()
5 - О классах
имеется 2 метода - staticmethod и classicmethod
О них замечательно рассказано на хабре, я просто процитирую.
Надеюсь это хоть кому-нибудь поможет понять как использовать декораторы.Статический метод (обёрнутый декоратором staticmethod) в принципе соответствует статическим методам в C++ или Java. А вот метод класса — это нечто более интересное. Первым аргументом такой метод получает класс (не экземпляр!), это происходит примерно так же, как с обычными методами, которые первым аргументом получают референс на экземпляр класса. В случае, когда метод класса вызывается на инстансе, первым параметром передаётся актуальный класс инстанса, это видно на примере выше: для порождённого класса передаётся именно порождённый класс.class TestClass(object):
@classmethod
def f1(cls):
print cls.__name__
@staticmethod
def f2():
pass
class TestClass2(TestClass):
pass
TestClass.f1() # печатает TestClass
TestClass2.f1() # печатает TestClass2
a = TestClass2()
a.f1() # печатает TestClass2