Básicos del Lenguaje

1

Guía de instalación y conceptos básicos

2

Archivos y slides del curso práctico de Python

3

IMPORTANTE: Instalando Ubuntu Bash en Windows para facilitarte el seguimiento del curso desde Windows.

4

¿Qué es la programación?

5

¿Por qué programar con Python?

6

Operadores matemáticos

7

Variables y expresiones

8

Presentación del proyecto

9

Funciones

10

Usando funciones en nuestro proyecto

11

Operadores lógicos

12

Estructuras condicionales

Uso de strings y ciclos

13

Strings en Python

14

Operaciones con Strings en Python

15

Operaciones con strings y el comando Update

16

Operaciones con strings y el comando Delete

17

Operaciones con strings: Slices en python

18

For loops

19

While loops

20

Iterators and generators

Estructuras de Datos

21

Uso de listas

22

Operaciones con listas

23

Agregando listas a nuestro proyecto

24

Diccionarios

25

Agregando diccionarios a nuestro proyecto

26

Tuplas y conjuntos

27

Tuplas y conjuntos en código

28

Introducción al módulo collections

29

Python comprehensions

30

Búsquedas binarias

31

Continuando con las Búsquedas Binarias

32

Manipulación de archivos en Python 3

Uso de objetos y módulos

33

Decoradores

34

Decoradores en Python

35

¿Qué es la programación orientada a objetos?

36

Programación orientada a objetos en Python

37

Scopes and namespaces

38

Introducción a Click

39

Definición a la API pública

40

Clients

41

Servicios: Lógica de negocio de nuestra aplicación

42

Interface de create: Comunicación entre servicios y el cliente

43

Actualización de cliente

44

Interface de actualización

45

Manejo de errores y jerarquía de errores en Python

46

Context managers

Python en el mundo real

47

Aplicaciones de Python en el mundo real

Conclusiones finales

48

Python 2 vs 3 (Conclusiones)

Clases bonus

49

Entorno Virtual en Python y su importancia: Python en el mundo real

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Decoradores en Python

34/49
Recursos

En esta clase pondremos en práctica lo aprendido en la clase anterior sobre decoradores.

Por convención la función interna se llama wrapper,

Para usar los decoradores es con el símbolo de @(arroba) y lo colocamos por encima de la función. Es un sugar syntax

*args **kwargs son los argumentos que tienen keywords, es decir que tienen nombre y los argumentos posicionales, los args. Los asteriscos son simplemente una expansión.

Aportes 100

Preguntas 17

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

DECORADORES EN PYTHON
Los decoradores sirven para ejecutar lógica del código antes y/o después de otra función, esto nos ayuda a generar funciones y código que pueda ser reutilizado fácilmente sin hacer más extenso nuestro código. Hay que recordar que si se genera una función dentro de otra solo existiera en ese scope(dentro de la función padre), si se quiere invocar una función varias veces dentro de otras se tiene que generar de manera global.

**args y kwargs**

Básicamente lo que hacen es pasar tal cual los valores de de los argumentos que se pasan a la función args hace referencias a listas y kwargs a elementos de un diccionario (llave: valor)

** args: **

def test_valor_arg(n_arg, *args):
    print('primer valor normal: ', n_arg)

    For arg in args:
	print('este es un valor de *args: ',arg)

    print(type(args))

if__name__ == '__main__':

    test_valor_args('carlos','Karla','Paola','Elena')
  • el tipo de valor y es una tupla
  • solo poniendo argumentos divididos por comas los convierte

**kuargs: **

def test_valor_kwargs(**kwargs):
    if kwargs is not None:
        for key,  value in kwargs.items():
            print('%s == %s' %(key,value))

    print(type(kwargs))

if __name__ == '__main__':

    test_valor_kwargs(caricatura='batman')
  • el valor que te da es un diccionario
  • toma los valores en los extremos de un signo igual

Este es un ejemplo usando los 2 en una función

def test_valor_kwargs_args(*args, **kwargs):
    print(type(kwargs))
    print(kwargs)
    print('----------')
    print(type(args))
    print(args)

if __name__ == '__main__':
    test_valor_kwargs_args('flash', 'batman', caricatura='batman', empresa = 'dc')

Acá está explicado y con ejemplos simples:
https://www.youtube.com/watch?v=DQXm6bIZgvk

Comparto dos artículos muy interesantes para entender mejor los temas tratados en la clase 👇🏼
–> https://recursospython.com/guias-y-manuales/argumentos-args-kwargs/
–> https://recursospython.com/guias-y-manuales/decoradores/

Aquí hay un vídeo donde explican bien el tema de los decoradores: Decoradores - Codigo Facilito

Estos temas que cuestan un poco asimilarlos deberían ser explicados de la forma mas sencilla posible, ya teniendo claro el concepto se puede volver tan complejo como se requiera.

Hice un micro juego de texto:

def upper(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)

        return result.upper()
    
    return wrapper

@upper
def say_my_name(name):
    if name == 'Heisenberg':
        return 'Youre Goddamn Right'
    else:
        name = input('Say my name! ')
        say_my_name(name)


if __name__ == '__main__':
    name = input('Now, say my name ')
    result = say_my_name(name)
    print(result)

les dejo este link: https://code.tutsplus.com/articles/understanding-args-and-kwargs-in-python--cms-29494 donde entenderán un poco más como usar args y kwargs en python. Súper útil.

*args:
1.Son todos los “N CANTIDAD” DE “Elementos posicionales” que puede recibir la función EJ:

def suma(*args):
	resultado = 0
    for valor in args:
       resultado = resultado + valor
   return resultado
    
print(suma(1,2,3,4,5,6,7,8,9)) #HASTA MAS ARGUMENTOS SI GUSTAS

**kwargs:
1.Son todos los “N CANTIDAD” DE “ARGUMENTOS CON SUS CORRESPONDIENTES VALORES” que puede recibir la funcion EJ:

def suma(**kwargs)
	print(kwargs)

suma(valor = 'Eduardo', z = 20 , x=2.0) #HASTA MAS ARGUMENTOS SI GUSTAS

Me parece mucho más fácil entender los decoradores en Python que entender un callback en Javascript

Dentro del wrapper de password_required se puede omitir el else debido a que dentro del if se ejecuta una sentencia return haciendo que en caso de cumplirse la condición lo que esta después de ella nunca se ejecuta.

*args : le pasamos una cantidad indefinida de parámetros ( args es un nombre definido por convención, le puedes poner el que tu quieras ).

**kwargs : le pasamos una cantidad indefinida de parámetros, pero ahora con su respectiva clave ( o llave ), veamos un ejemplo:

def func(numero_1, numero_2):
    print(numero_1 + numero_2)

func(numero_1 = 5, numero_2 = 3)

# Vemos aqui que la llave es numero_1 y numero_2

Como vemos la sintaxis “numero_1 = 5” representa al parámetro con su respectiva clave, por eso se utiliza como convención “**kwargs” (te recuerdo que le puedes poner el nombre que quieras)

Aca el link que habla sobre *args y **kwargs me parecio sencillo de entender

Hay que tener en cuenta 2 cosas: 1 si la funcion que estamos decorando recibe parametros, es necesario los *args y **kwargs, de lo contrario no es necesario. 2 se puede crear otra funcion que encierre nuestro decorador, para pasarle parametros al decorador, osea podemos a Los decoradores cambiar el comportamiento con parametros propios.

Este tema es bastante “blows my mind” Cuando se tenga un poco de experiencia y necesiten un método para “encapsular” la lógica del llamado a la API de las contraseñas en el backend lo van a entender mejor y van a saber de la importancia.

Por eso David en el min 3:02 dice que desde main o desde el punto de entrada no se puede llamar a la función wrapper() agregando así una capa de seguridad a nuestra lógica de manejo de login’s. Como ven el método main no se llama en ningun momento la función wrapper que contiene la lógica para acceder.

Les dejare por separado los scripts que hizo el profe con pequeños cambios

aca el primero:

PASSWORD = "hello123"


def password_required(func):
	def wrapper():
		password = input("What is the password? ")

		if password == PASSWORD:
			return func()
		else:
			print("The password is not correct")

	return wrapper

@password_required
def needs_password():
	print("The password is correct, welcome")


if __name__ == "__main__":
	needs_password()

y aca el segundo:

your_name = input("What is your name? ")


def upper(func):
	def wrapper(*args, **kwargs):
		result = func(*args, **kwargs)

		return result.upper()

	return wrapper


@upper
def say_your_name(name):
	return f"Hola, {name}"


if __name__ == '__main__':
	print (say_your_name(your_name))

Consideren que los decoradores al retornar una función nueva esta no hereda las propiedades de la función original, para solucionar esto deben usar el decorador wraps del módulo functools, de esta manera las propiedades originales persisten.

from functools import wraps

def decorador_sinwraps(func):
    def wrapper(*args, **kwargs):
        """Main wrapper | Decorador"""
        return func(*args, **kwargs)
    return wrapper

def decorador_conwraps(func):

    @wraps(func)
    def wrapper(*args, **kwargs):
        """Main wrapper | Decorador"""
        return func(*args, **kwargs)
    return wrapper

def func1(valor: int):
    """Función Quintuplicadora"""
    return valor * 5

@decorador_sinwraps
def func2(valor: int):
    """Función Duplicadora"""
    return valor * 2

@decorador_conwraps
def func3(valor: int):
    """Función Triplicadora"""
    return valor * 2

# Pruebas de persistencia de documentación.

print(func1.__doc__)  # Función Quintuplicadora

# Se esperaría "Función Duplicadora" sin embargo resulta:
print(func2.__doc__)  # Main wrapper | Decorador

# al usar wraps se "heredan" las propiedades de la función orginal:
print(func3.__doc__)  # Función Triplicadora

***args ** es para enviar tuplas como parametro a una función.
Podemos enviar esto:

func_args ('A', 'B', 'C', 'D', 'E')

y recibirlo así:

def func_args (n_arg, *args):

n args contiene el 1er elemento ‘A’
*args contiene la tupla (‘B’, ‘C’, ‘D’, ‘E’)

**kwargs es para enviar diccionarios como parametros a una función.
Podemos enviar esto:

func_kwargs(caricatura = 'batman', pelicula = 'KillBill', serie = 'BigBang')

y recibirlo así:

def func_kwargs(**kwargs):

**kwargs contiene el diccionario.

Aplicando los args a un ejercicio simple

"""
Definir una función max_de_tres(), que tome tres números como argumentos
y devuelva el mayor de ellos.
"""

def max_number(n_arg, *args):
    #print('Primer valor normal: ', n_arg)
    for i in range(len(args)):
        if n_arg > args[i]:
            pass
        else:
            n_arg = args[i]
        #print('Este es el valor de *args: ', args[i])
    return n_arg


def max_number_2(number1, number2, number3):
    if number1 > number2:
        if number1 > number3:
            return number1
        else:
            return number3
    else:
        if number2 > number3:
            return number2
        else:
            return number3


if __name__ == '__main__':
    number1 = None
    number2 = None
    number3 = None

    while not number1:
        number1 = input('What is the first number? ')

    while not number2:
        number2 = input('What is the second number? ')

    while not number3:
        number3 = input('What is the third number? ')

    print('-' * 30)
    print(max_number(number1, number2, number3))

    print('-' * 30)
    print(max_number_2(number1, number2, number3))

    print('-' * 30)
    print(max(number1, number2, number3)) # esta es la función max() que tiene incorporada python

Aquí dejo un ejemplo muy sencillo que usé para practicar decoradores. A pesar de lo sencillo me tomó bastante tiempo corregir la gran cantidad de errores que se prensentaron para completarlo, sobre todo al tratar de usar los **kwargs dentro del wrapper

"""Evalua si una persona esta en la lista de invitados"""
import functools

amigo = {'name':'Alex','lastname':'Zambrano'}

GUESTS = [{'name':'Jose','lastname':'Perez'},{'name':'Pedro','lastname':'Sanchez'}]

def invitado(func):
    @functools.wraps(func)
    def wrapper(*args,**kwargs):
        found = False
        for id,guest in enumerate(GUESTS):
            if guest['name'] == kwargs['name'] and guest['lastname'] == kwargs['lastname']:
                func(*args,**kwargs)
                found = True
                break
        if found == False:    
            print('{} {} no se encuentra en la lista de invitados'.format(kwargs['name'],kwargs['lastname']))

    return wrapper
        

@invitado
def generate_identification_card(**kwargs):
    print('La identificacion para {} {} ha sido generada'.format(kwargs['name'],kwargs['lastname'])) 

generate_identification_card(name=amigo['name'],lastname=amigo['lastname'])```

Hola creé un decorador que me parece es bastante simple y puede ser bastante útil

from datetime import datetime
import time
def  measure execution time(fun):
	def  wrapper(*args, **kargs):
        	start = datetime.now()
		func(*args, **kargs)
		end = datetime.now() 
		print('El tiempo de ejecucion es de :{}'.format((end - 		start).total_seconds()))
	 return wrapper

Si aplican este decorador a cualquiera de sus funciones van a poder observar cual es el tiempo de ejecución de su función.
Además, me parece que nos ayuda a comprender un poco mejor el uso de decoradores.

Aquí les dejo 2 enlaces que les van a servir para complementar lo visto en esta clase.

http://www.pythondiario.com/2018/06/decoradores-en-python.html
https://recursospython.com/guias-y-manuales/argumentos-args-kwargs/

*args son variables que pasamos pero no son keywords es decir func (‘pera’’,‘manzana’)
**kwargs son variables que llamamos keywords y se la pasamos a la func es decir func(fruta=‘manzana’, auto=‘fiat’)

Usando estas cosas permitimos mandar X cantidad de variables a una funcion, sin saber la cantidad.

Falta mucho en este curso..... necesitamos una explicación más profunda del porqué de las cosas......

Quizás ya lo sabían pero yo no.

Si haces esto

>>> name = 'mANUEL'
>>> name.capitalize()

Imprime así.

Manuel

Parece ser que en python2 la funcion input() regresa el tipo que se le asigne al momento de escribir en la terminal, recomiendo parsear a string la contraseña para evitar errores.

PASSWORD = '12345'

def password_required(func):
    def wrapper():
        password = str(input('What is your password? '))
        if password == PASSWORD:
            return func()
        else:
            print('Password incorrect')
    return wrapper

@password_required
def needs_password():
    print('password is correct')

if __name__ == "__main__":
    needs_password()

.
Dejo acá mi código https://github.com/behagoras/basic-python/tree/decorators

*args,**kwargs

Siguiendo el ejemplo de Josué, lo extendí un poco más y arreglé varios errores, y ahora solo te dice el nombre si la contraseña es correcta.

PASSWORD = '12345'

def password_requeried(func):
  def wrapper():
    password = input("Cual es tu contraseña?")

    if password == PASSWORD:
      return func()
    else:
      print('La contraseña no es correcta')

  return wrapper

def upper(func):
  def wrapper(*args, **kwargs):
    argumentos = []
    for arg in args:
      argumentos.append(arg.lower().capitalize())

    return func(" ".join(argumentos), **kwargs)

  return wrapper


@password_requeried
def need_password():
  print('La contraseña es correcta')
  return True


@upper
def say_my_name(name):
  print('Hola {}'.format(name))

if __name__=='__main__':
  login = need_password()
  if login != None:
    say_my_name('ENRIQUE', 'MARRERO')

Aproveché estas herramientas de decorador y recursividad para ponerle contraseña a nuestro proyecto de Lista de Clientes, además uso el módulo getpass para pedir la contraseña por consola y que no se muestre el texto, me gustaría que se pudieran ver ( * ) por cada letra que ingrese pero no he podido, si alguien sabe como, porfa comentenlo.

PASSWORD='python'
import getpass
import sys
def  bloqueo(program):
    def  meter_clave():
        clave=getpass.getpass("Indica tu contraseña (exit), para salir: ")
        if clave == PASSWORD:
            return program()
        elif clave=='exit':
            sys.exit()            
        else:
            print('Contraseña incorrecta, pruebe de nuevo\n')
            return meter_clave()
    return meter_clave()

En el minuto 9:08
*(asterisco) y **(doble asterisco)
¿No son apuntadores?

La mejor explicación que encontré en este link

tengan en cuenta que lo importante son los simbolos * y ** los nombres pueden ser cualquier cosa pero por convencion usemos args y kwargs 😃

Una simple función que define *args y **kwargs

def Func(*args,**kwargs):
     
    for arg in args:
        print arg

    for item in kwargs.items():
        print item
         
print Func(1,x=7,u=8)

Que imprime como resultado:

1
('x', 7)
('u', 8)

Más info

PASWORD = '12345';

def password_required(fn):
  def wrapper():
    password = input('Cuál es tu contraseña ?: ');

    if password == PASWORD:
      fn();
    else:
      print('La contraseña no coincide.');
  
  return wrapper;


@password_required
def needs_password():
  print('La contraseña es correcta');

def upper(fn):
  def wrapper(*arg, **kwarg):
    return fn(*arg, **kwarg).upper();
  
  return wrapper;

@upper
def say_hey(name):
  return 'Hola, {}'.format(name);

if __name__ == '__main__':
  name_user = input('Cúal es tu nombre?: ');

  print(say_hey(name_user));```

DECORADORES Concepto clave para ser programadores en python.
un ejemplo:

# Decoradores en forma de función

# El nombre de la funcion es el nombre del decorador y recibe la funcion que decora (print_text).
def decor(func):
    def wrap():
        print("="*12)
        func()
        print("="*12)
    return wrap

@decor
def print_text():
    print("Hola Mundo!!!")



if __name__ == '__main__':
    print_text()

Comparto mi código con el cual agrego un decorador al menú principal.
El usuario debe ingresar una contraseña para acceder, se le permiten 3 intentos, y dado que el usuario es de olvidar las contraseñas el programa le sopla cual es la contraseña correcta.

```python PASSWORD = '12345' def password_required(func): def wrapper(*args, **kwargs): password = input('¿Cuál es tu contraseña? ') if password == PASSWORD: return func(*args, **kwargs) else: print('Contraseña incorrecta') return wrapper def upper(func): def wrapper(*args, **kwargs): result = func(*args, **kwargs) if result is not None: return result.upper() return wrapper #@upper @password_required def needs_password(): return 'La contraseña es correcta' @upper def say_my_name(name): print('Hola, {}'.format(name)) if __name__ == '__main__': result = needs_password() if result: print(result) say_my_name('Nelly te amo') ```PASSWORD = '12345' def password\_required(func): def wrapper(\*args, \*\*kwargs): password = input('¿Cuál es tu contraseña? ') if password == PASSWORD: return func(\*args, \*\*kwargs) else: print('Contraseña incorrecta') return wrapper def upper(func): def wrapper(\*args, \*\*kwargs): result = func(\*args, \*\*kwargs) if result is not None: return result.upper() return wrapper \#@upper @password\_required def needs\_password(): return 'La contraseña es correcta' @upper def say\_my\_name(name): print('Hola, {}'.format(name)) if \_\_name\_\_ == '\_\_main\_\_': result = needs\_password() if result: print(result) say\_my\_name('Nelly te amo')

Lo practique para entender mejor los *args and **kwargs muy bueno, útiles, y el decorador también lo entiendo como donde lo ubique @ la function debajo de este trabajara dependiendo de su decorador @

Creo que es mala practica que el profesor escriba el nombre de las funciones en inglés y los mensajes en español

Decorador que separa una palabra.

def separate_fn(func):
    def wrapper(*args, **kwargs):

        ns=func(*args, **kwargs).replace(' ','|')
        return ns 
    return wrapper

@separate_fn
def full_name(fullname):
    return fullname


def run():
    print(full_name(input('enter fullname: ')))

if __name__=='__main__':
    run()
<
PASSWORD = '12345'


def password_required(func):
    def wrapper():
        password = input('Cual es tu contrasena? ')

        if password == PASSWORD:
            return func()
        else:
            print('La contrasena no es correpta')
    
    return wrapper


@password_required
def needs_password():
    print('La contrasena es correcta')


def upper(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)

        return result.upper()

    return wrapper  


@upper
def say_my_name(name):
    return 'Hola, {}'.format(name)

if __name__ == '__main__':
    needs_password()
    print(say_my_name('Cristian'))

> 

Tengo una pregunta.
En el primero ejemplo se uso decoradores sin que la función tenga parámetros y se usó ‘print’. El programa corrió sn problemas.
En cambio en el segundo ejemplo se presentó un error porque, explocó Davir, qe se debe a que se está usando ‘print’ cuando debería ser ‘retrun’.
Alguien entiende eso?

Mi code, con notas de sus aportes:

def decorador(func):
    def wrapper(): #Este pedo esta raro porque si quitas kwargs siguen pasando los dos argumentos
        print('antes')
        resultado = func()#Y si le pones otro nombre tmb sirve
        print('despues')
        return resultado
    return wrapper

@decorador
def decorando():
    print(f'El pepe')



def decorador_args_and_kwargs(func):
    def wrapper(*args, **kwargs): #Este pedo esta raro porque si quitas kwargs siguen pasando los dos argumentos
        print('antes')
        resultado = func(*args, **kwargs)#Y si le pones otro nombre tmb sirve
        print('despues')
        return resultado
    return wrapper

@decorador_args_and_kwargs
def decorando_args_and_kwargs(name, nam = 'po'):
    print(f'El {name, nam}')


if __name__ == '__main__':
    decorando()
    print('*' * 50)
    decorando_args_and_kwargs('chuy') 


#EXPLICACIÓN DE *ARGS | ostia puta esto está muy crack
# def test_valor_arg(n_arg, *args):
#     print('primer valor normal: ', n_arg)

#     print(type(args))
#     for arg in args:
# 	    print('este es un valor de *args: ',arg)
#     print(args)


# if __name__ == '__main__':
#     test_valor_arg('carlos','Karla','Paola','Elena')


#EXPLICACIÓN MAMALONA DE LOS KWARGS | BASICAMENTE HACE DICT LOS ARGUMENTO POR DEFECTO | COOL
# def kwargs_test(**kwargs):
#     for key, value in kwargs.items():
#         print(f'Key: {key} | Value: {value}')
#     print(kwargs)
#     print(type(kwargs))

# if __name__ == '__main__':
#     kwargs_test(el='pepe')

Un decorador es básicamente convertir una función en el argumento de otra función

yo los entiendo ? siento que es de los profesores que menos nos entiende

say_my_name('Heissenberg')

Excelente esta clase, había leído sobre decoradores cientos de veces y no me había quedado tan claro el tema como en esta ocasión con esta clase, es genial!!!

En este video explican muy bien los decoradores, con ejemplos muy claros.

https://www.youtube.com/watch?v=DlGPvq9r6Q4

Nosotros normalmente, utilizamos el nombre de la función interna llamada wrapper.

cual es la definición formal de un decorador? em queda claro para que se usa y como se usa pero no que es

Investigando un poco más sobre el sugar syntax o Syntactic sugar encuentro que estos son agregados al lenguaje que sin ellos el lenguaje podría realizar las mismas funciones, pero podrían llevarse más lineas de código o que sea más fácil de leer, esto viene desde hace mucho tiempo atras y en muchos lenguajes se utilizan.

Se tiene que algunos procesadores de lenguaje y compiladores llevan estos Syntactic sugar a niveles más primitivos antes de realizar el procesado, a esto se le llama “desugaring” o desendulzar.

Es interesante también que uno de los Syntactic sugar de Python son las list comprehension que vimos anteriormente.

muy interesante gracias profe

Genial!!

No conocía este concepto de decoradores, pero ahora lo tengo muy claro

excelente! lo de los decoradores

este era un concepto del curso anterior que no me habia quedado muy claro, se utilza en el siguiente curso de ingenieria de datos, ojo, si no entendiste completamente, practica este punto.

Excelente, Decoradores!!.
Gracias!!

En este tema/video, faltó que dieras más detalles y una mejor explicación del “flujo del procesamiento de los datos dentro de los decoradores” que usaste como ejemplo para poder comprender correctamente cómo es que un decorador funciona “sobre” una función.

¿No son apuntadores?

04:34 Porque no se utiliza los parentesis en el llamado de la funcion wrapper?

usar las palabras wrapper y fun() forma parte de los decorators?

Al pasar los args en el wrapper podemos cambiar el resultado usando los argumentos de entrada, para este caso podemos utilizar args que tome la primer variable (name) y cambiar el mensaje de regreso, como se ve en el siguiente código.

def upper(func):
  def wrapper(*args, **kwargs):
    result = func(*args, **kwargs)

    # return result.upper()
    return "Mi gran amigo {}".format(args[0]).upper()

  return wrapper

Decoradores en Python son los semejantes que recursividad en Javascript (es el mismo proceso??)… y si es así esto no llena el stack de memoria, existe memoizacion en python ??

Una contraseña Hasheada con algoritmo MD5 xD

Buen día,

Código de la clase.


PASSWORD = '12345'


def password_required(func):
    def wrapper():
    	password = input('¿Cual es tu contraseña?')

    	if password == PASSWORD:
    		return func()
    	else:
    		print('La contraseña no es correcta')

    return wrapper


#Decoradores
@password_required
def needs_password():
    print('La contraseña es correcta')


def upper(func):
    def wrapper(*args,**kwargs):
        result = func(*args,**kwargs)

        return result.upper()

    return wrapper


@upper
def say_my_name(name):
    return 'Hola, {}'.format(name)


if __name__ == '__main__':
	print(say_my_name('Walter'))
    #needs_password()

cuando definimos nuestro punto de entrada con

if __name__ == '__main__'

para el caso de este archivo que lo llamamos decorators.py porque no cambiamos el nombre main por decorators ?

por si a alguien le ayuda

PASSWORD = '12345'

def password_requeried(func):
  def wrapper():
    password = input("Cual es tu contraseña?")
    if(password==PASSWORD):
      func()
    else:
      print('La contraseña no es correcta')

  return wrapper

def upper(func):
  def wrapper(*args, **kwargs):
    aa = []
    for arg in args: 
      aa.append(arg.upper())
      func("".join(aa), **kwargs)
  return wrapper


@password_requeried
def need_password():
  print('La contraseña es correcta')

@upper
def say_my_name(name):
  print('hola {}'.format(name))

if __name__=='__main__':
  need_password()
  say_my_name('Chaqui')

Tan fácil son los decoradores en Python, por eso me gusta este lenguaje!

En C++ era un poco más verboso

Un decorador nos permite ejecutar lógica antes y después de una función.

Modifique el codigo del profesor e hice que solo se cambie el nombre que se manda en un principio a mayusculas y no todo el texto espero les sirva. Recuerden que args es una tupla

PASSWORD = '12345'
def password_required(func):
	def wrapper():
		password = input('Cual es tu contrasena? ')
		if password == PASSWORD:
			return func()
		else:
			print('La contrasena no es correcta')
	return wrapper

@password_required
def needs_password():
	print('La contrasena es correcta')

def upper(func):
	def wrapper(*args,**kwargs):
		name2 = args[0].upper()
		result = func(name2)
		return result

	return wrapper

@upper
def say_my_name(name):
	return 'Hola {}'.format(name)

if __name__ == '__main__':
	print(say_my_name('Rodolfo'))

En que cursos de plats podemos construir nuestras propias bases de datos?

Para que una función tome una cantidad indefinida de argumentos, se utiliza la expresión *args.
Eje:


 def f(*args): 
	return args

f(1, 5, True, False, "Hello, world!")
	(1, 5, True, False, 'Hello, world!')

aqui my codigo un poco modificado pero funciona

def say_my_name(*args):
    for name in args:
        print(name.upper())
    


if __name__ == '__main__':
    needs_password()

    say_my_name("diego", "carlos,", "rosa")```

David, muy buena la primer ejemplo, pero hacen mas falta ejemplos para la opcion dos de los decoradores, siento a mi parecer que esta seccion falto ejemplos

En este enlace se explica muy bien el tema de *args y **kwargs

Los decoradores son herramientas muy útiles y, una vez entendidos correctamente, fáciles de implementar. Así que nos hemos propuesto ir paso por paso en el conocimiento de ellos, para entender de qué se trata y cómo emplearlos.

Yo eso lo había visto con algoritmos de optimización. No sé si sean decoradores pero parecen. Uno les da la función de costo, el tipo de algoritmo, con sus parámetros y ahí llega a encontrar el óptimo iterando sobre la función. Aunque no sé si se llamen igual, pero puede que sí. Si alguien sabe, que por fa me confirme.

Tengo entendido que se puede resumir un poco mas la parte de if else statement seria así:

return func() if password==PASSWORD else print("La contraseña no es correcta")

Me podrían dar su opinión si es útil usarse así con respecto a memoria u otros factores, de ante mano gracias.

def password_required(func):
    def wrapper():
        password = input('Cual es tu contraseña? ')

        if password == PASSWORD:
            return func()
        else:
            print('La contraseña no es correcta.')
    
    return wrapper

@password_required
def needs_password():
    print('La contraseña es correcta')


def upper(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)

        return result.upper()
    
    return wrapper

@upper
def say_my_name(name):
    return ('Hola {}'.format(name))


if __name__ == '__main__':
    print(say_my_name('luifer'))

Les comparto cierta información que me aclaro un poco la clase:

Al escribir una función podemos definir parametros por defecto en caso de que el usuario omita enviarlos en la llamada, en este caso estaremos creando un kwargs.
Los kwargs son parametros que no necesitan respetar una posición al momento de llamar la funcion, como si lo deben hacer argumentos simples que de no declararlos provocarían que el sistema arroje un error.

La función de *args es indicar a la función que recibirá una cantidad de argumentos indefinidos. Por ejemplo podemos pasar una lista de elementos y esa lista sera guardada en la variable args. El mismo funcionamiento tiene **kwargs el cual puede interpretarse como si enviaramos un diccionario de una cantidad de elementos indefinidos.

Luego, las funciones o los llamados de una función(definamoslo como “función()”) pueden ser enviados como parámetros o almacenados en una variable.
El decorador posee la declaración de una función interna la cual solo es invocada dentro del scope de la función externa, pero existe la posibilidad de invocarla fuera de esta si la almacenamos en una variable y luego la llamamos con los parametros adecuados.

Lo que hacen los decoradores, es cambiar algo antes de que llegue el valor a la función.

Lo que hacen los decoradores, es cambiar algo antes de que llegue el valor a la función.

Si no expresas el return, entonces automáticamente la función retorna None.

para utilizar los decoradores, utilizamos el símbolo de arroba o el at.

En python podemos definir una función dentro de una función, al hacerlo, definimos el scope de la función embebida.

ojo, que las contraseñas van en bases de datos.

<h3>Por posición</h3>

Para recibir un número indeterminado de parámetros por posición *args

def indeterminados_posicion(*args):
    for arg in args:
        print(arg)
    
indeterminados_posicion(5,"Hola",[1,2,3,4,5])
<h4>salida</h4>
5
Hola
[1, 2, 3, 4, 5]
<h3>Por nombre</h3>

Para recibir un número indeterminado de parámetros por nombre (clave-valor) *Kwargs.

def indeterminados_nombre(**kwargs):
    for kwarg in kwargs:
        print(kwarg," ", kwargs[kwarg])

indeterminados_nombre(n=5,c="Hola",l=[1,2,3,4,5])   
<h4>salida</h4>
n   5
c   Hola
l   [1, 2, 3, 4, 5]
<h3>Por posición y nombre</h3>

Si queremos aceptar ambos tipos de parámetros simultáneamente.

def super_funcion(*args,**kwargs):
    t = 0
    for arg in args:
        t+=arg
    print("Sumatorio es",t)
    for kwarg in kwargs:
        print(kwarg," ", kwargs[kwarg])
​
super_funcion(10,50,-1,1.56,10,20,300,nombre="Hector",edad=27)
<h4>salida</h4>
Sumatorio  es 390.56
nombre   Hector
edad   27

Caso de uso de decoradores: Imaginate que tienes un programa donde existe un numero N de funciones pensemos 200 funciones por que es un proyecto grande y resulta que ahora tienen que modificar gran parte de las funciones para agregarle otra utilidad entonces hacerlo una por una seria algo desastrozo que pudiese dañar el codigo entonces aqui es donde entra el caso de uso de los decoradores, donde simplemente crearemos funciones para añadirle funcionamiento por ejemplo el mismo funcionamiento a dichas funciones que necesitamos mejorar y en este caso no tienen que ser todas sino solamente las que queramos o elijamos


Codigo de ejemplo:

<def funcion_decoradora(funcion_parametro):
    def funcion_interior():
        #acciones adicionales que decoraran
        print("Vamos a realizar un calculo: ")
        #ahora llamamos a la funcion parametro para agregar la funcionalidad
        funcion_parametro()
        #acciones adicionales para decorar
        print("Hemos terminado el calculo")
        #ahora debemos retornar la funcion que devuelve la funcion decoradora que es donde se encuentra las acciones en este caso:
    return funcion_interior
#Una vez teniendo el decorador listo ahora lo que necesitamos es especificar en que funcion vamos a colocar el decorador para ello:
@funcion_decoradora #Con esto estamos indicando que al momento de ejecutar suma, le agregamos funcionalidades extras con la funcion decoradora
#la funcion parametro realmente lo que se vuelve a la funcion que queremos decorar en este caso suma asi que dentro del compilador se sustituye
def suma():
    print(15+20)
@funcion_decoradora
def resta():
    print(30-10)
def run():
    suma()
    resta()
if __name__ == '__main__':
    run()> 

IMPORTANTE Hay que recordar que los identificadores de funciones variables objetos etc, tienen que ser definidos exactamente para poder leerlos bien al momento de interpretar tu codigo en el futuro y para que otros desarrolladores lo puedan leer bien ademas esta es una excelente practica para mejorar como desarrollador

Para definir funciones con un número variable de argumentos colocamos un último parámetro para la función cuyo nombre debe precederse de un signo *:

def varios(param1, param2, *otros):
	for val in otros:
	print val

varios(1, 2)
varios(1, 2, 3)
varios(1, 2, 3, 4)

Esta sintaxis funciona creando una tupla (de nombre otros en el ejemplo) en la que se almacenan los valores de todos los parámetros extra pasados como argumento. Para la primera llamada, varios(1, 2), la tupla otros estaría vacía dado que no se han pasado más parámetros que los dos definidos por defecto, por lo tanto no se imprimiría nada. En la segunda llamada otros valdría (3, ), y en la tercera (3, 4).
También se puede preceder el nombre del último parámetro con **, en cuyo caso en lugar de una tupla se utilizaría un diccionario. Las claves de este diccionario serían los nombres de los parámetros indicados al llamar a la función y los valores del diccionario, los valores asociados a estos parámetros.

muy buena explicación

Excelente ejercicio. aquí un ejemplo con otros nombres para entender mejor

def funcion_decoradora(funcion_parametro):

	def funcion_interior():
		# Acciones adicinales que decoran
		print('Vamos a realizar un calculo: ')

		funcion_parametro()

		# Acciones adicinales que docoran

		print('Hemos terminado el calculo')

	return funcion_interior


@funcion_decoradora
def suma():
	print(150 + 2220)


def resta():
	print(33 - 10)


suma()	
resta()

Si el tema de los decoradores es tan importante como dicen: porque tratan de embutirlo todo en un solo capitulo? Dividir este capitulo en dos seria mas conveniente

Ejemplo del profe

PASSWORD = '12345abcde'


def password_require(func):
    def wrapper():
        password = input('What is your password? ')

        if password == PASSWORD:
            return func()
        else:
            print('Password is incorect')

    return wrapper

@password_require
def needs_password():
    print('The password is correct:')


if __name__ == '__main__':
    needs_password()

revise la version de python que estoy usando y es la 3.7.3, pero para que el scrip funcionara correctamente tuve que usas la funcion

raw_input()

en lugar de

input()

al parecer si usaba input me recibia los datos del teclado de un tipo diferente a string
alguien sabe si es normal?
busque en foros de python y dicen que raw_input “ya no se usa” en python 3