# -*- coding: utf-8 -*-

# def my_decorator(function_to_decorate):
# 	def the_wrapper_around_the_original_function():
# 		print("Этот код работает до вызова функции")
# 		function_to_decorate()
# 		print("Этот код работает после вызова функции")
# 	return the_wrapper_around_the_original_function


# def stand_alone_function():
# 	print("Эта функция не изменяется")


# @my_decorator
# def another_stand_alone_function():
# 	print("Оставль меня в покое")


# another_stand_alone_function()

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Передача аргументов в декорируемую функцию

def a_decorator_passing_argument(function_to_decorate):
	def a_wrapper_accepting_arguments(arg1, arg2):
		print "Смотри, что я получил:", arg1, arg2
		function_to_decorate(arg1, arg2)
	return a_wrapper_accepting_arguments


@a_decorator_passing_argument
def print_full_name(first_name, last_name):
	print "Меня зовут", first_name, last_name

# print_full_name("Питер", "Венкман")

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Декорирование методов 

def method_friendly_decorator(method_to_decorate):
	def wrapper(self, lie):
		return method_to_decorate(self, lie)
	return wrapper


class Lucy(object):

	def __init__(self): 
		self.age = 21

	@method_friendly_decorator
	def sayYourAge(self, lie):
		print 'Мне %s, а ты бы сколько дал?' % (self.age + lie)


# l = Lucy()
# l.sayYourAge(-3)
	
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

def a_decorator_passing_arbitrary_arguments(function_to_decorate):
	def a_wrapper_accepting_arbitrary_arguments(*args, **kwargs):
		print "Передали ли мне что-нибудь?:"
		print args
		print kwargs
		function_to_decorate(*args, **kwargs)
	return a_wrapper_accepting_arbitrary_arguments

@a_decorator_passing_arbitrary_arguments
def function_with_no_argument():
	print "No argument here"

# function_with_no_argument()

@a_decorator_passing_arbitrary_arguments
def function_with_arguments(a, b, c):
    print a, b, c

# function_with_arguments(1, 2, 3)

@a_decorator_passing_arbitrary_arguments
def function_with_named_arguments(a, b, c, platypus="Почему нет?"):
	print "Любят ли %s, %s и %s утконосов? %s" % (a, b, c, platypus)


# function_with_named_arguments("Билл", "Линус", "Стив", platypus="Определенно!")


class Mary(object):

	def __init__(self):
		self.age = 31

	@a_decorator_passing_arbitrary_arguments
	def sayYourAge(self, lie=-3):
		print 'Мне %s, а ты бы сколько дал?' % (self.age + lie)


# m = Mary()
# m.sayYourAge()

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

def decorator_maker_with_arguments(decorator_arg1, decorator_arg2):
	print "Я создаю декораторы! И я получил следующие аргументы:", decorator_arg1, decorator_arg2
	def my_decorator(func):
		print "Я - декоратор. И ты все же смог передать мне эти аргументы:", decorator_arg1, decorator_arg2
		def wrapped(function_arg1, function_arg2):
			print ("Я - обёртка вокруг декорируемой функции.\n"
                  "И я имею доступ ко всем аргументам: \n"
                  "\t- и декоратора: {0} {1}\n"
                  "\t- и функции: {2} {3}\n"
                  "Теперь я могу передать нужные аргументы дальше"
                  .format(decorator_arg1, decorator_arg2, function_arg1, function_arg2))
			return func(function_arg1, function_arg2)
		
		return wrapped
	
	return my_decorator


@decorator_maker_with_arguments("Леонард", "Шелдон")
def decorated_function_with_arguments(function_arg1, function_arg2):
    print ("Я - декорируемая функция и я знаю только о своих аргументах: {0}"
           " {1}".format(function_arg1, function_arg2))
 
 
decorated_function_with_arguments("Раджеш", "Говард")