Interesante y utilidad de python. Parte 2

En el artículo anterior, examinamos varios puntos interesantes del lenguaje python, por supuesto, no se limitan a un artículo, por lo que continuaremos.

Un comentario examinó el siguiente código:

SEX = 'Female', 'Male' sex = SEX[True] # -> Male sex = SEX[False] # -> Female 

Funciona porque el tipo de datos lógicos es equivalente a 0 y 1, además, al principio no había ningún tipo especial y se usaban los valores 0 y 1. Y cuando se ingresó, decidimos heredar del todo.

 print(int.__subclasses__()) # -> [<class 'bool'>] 

Pero volviendo a obtener los valores de la lista, digamos que tenemos los siguientes datos:

 books = [["Sherlock Holmes", "Arthur Conan Doyle", 1986, True, 12.51], ["The Lost World", "Arthur Conan Doyle", 2015, False, 5.95], ["The Art of Computer Programming", "Donald E. Knuth ", 2017, True, 190.54] ] 

Por supuesto, no nos referimos a los valores mediante índices codificados. Puede crear una constante, por ejemplo AUTOR y especificarla, pero puede ir más allá:

 TITLE_AUTHOR = slice(0, 2) PRICE_IN_STOCK = slice(3, 5) print(books[0][TITLE_AUTHOR]) print([book for book in books if book[PRICE_IN_STOCK] > [True, 10.0]]) 

Podemos crear un objeto de corte e indicarle en qué índices se ubican los campos de interés. Incluso podemos ser lo suficientemente valientes como para escribir algo similar a la última línea de este bloque, que muestra libros disponibles en el almacén y más caros que 10. Este código funcionará, ya que la comparación de listas y tuplas se realiza lexicográficamente: primero se comparan los primeros elementos, luego el segundo y así sucesivamente, es decir, cualquier objeto cuyo "campo" in_stock sea falso será más pequeño que la lista [True, 10.0], ya que Verdadero> Falso.

Nota: por supuesto, este código no debe usarse en proyectos, pero es mejor limitarse a obtener solo algunos valores para el segmento, es mejor hacer selecciones en la base de datos, ya sea en Pandas o como un método de la clase Libro. Puede usar namedtuple y escribir un pequeño módulo donde colocar métodos con selecciones similares.

Ya hemos considerado los argumentos que se pueden pasar a la función solo por clave. Recientemente, mientras estudiaba la documentación para la función bool , encontré un subíndice:
Cambiado en la versión 3.7: x ahora es un parámetro solo posicional.
Ahora PEP 570 está en desarrollo, lo que abrirá la posibilidad de establecer dichos parámetros, esto puede ser útil cuando el nombre del parámetro no importa, como, bool (), pow (), etc.

El borrador de sintaxis se ve así:

 def name(positional_only_parameters, /, positional_or_keyword_parameters, *, keyword_only_parameters): 

Volviendo a la función bool, que funciona igual que verificar condiciones y bucles cuando ejecuta código

 if obj: #  while obj: 

Python realiza un procedimiento bastante interesante para generar un valor booleano:

  1. Si el objeto implementa el método __bool __ (), se devuelve el resultado de llamar a este método
  2. De lo contrario, se verifica si el método __len __ () está implementado; si es así, se verifica que regrese, si es 0, entonces el resultado será Falso.
  3. Si no se implementa ninguno de los métodos, se devuelve True.

 class A: pass a = A() print(bool(a)) # -> True 

Los enteros implementan el método __bool__, las colecciones estándar no lo implementan, pero implementan el método __len__:

 print(dir(int)) # -> ['__abs__', '__add__', '__and__', '__bool__', '__ceil__', ... print(dir(list)) # -> ['__add__', '__class__', '__contains__', ... 

En otro comentario , se dio el comportamiento "no estándar" de los atributos de clase:

 class Example: arr=[] def __init__(self): pass a = Example() b = Example() a.arr.append(1) print(a.arr) # -> [1] print(b.arr) # -> [1] print(Example.arr) # -> [1] 

Es muy importante distinguir entre los atributos de una clase y un objeto ; los atributos de un objeto se crean, de repente, a partir del objeto.
Es importante comprender que todos los campos y métodos declarados en el cuerpo de la clase pertenecen a la clase. Para crear un atributo para un objeto, debe asignarlo al objeto, en el método de clase a través de self o en el texto del programa, a través de la variable de objeto.

Si se confunde, analicemos el código anterior, se crean dos instancias de la clase, después de lo cual se agrega 1 al campo arr a través de uno de los objetos. Pero no existe tal atributo en el objeto, el constructor está vacío, por lo que Python busca este atributo en la clase y lo encuentra, sin embargo, es compartido por todas las instancias de la clase. Puede verificar que este es el atributo de la clase en la última línea, ya que el acceso a la clase por el nombre de este atributo no generó ningún error.

Al aprender un nuevo idioma, es importante comprender que cada idioma tiene su propia filosofía, y no todos los idiomas deben tener la palabra clave estática. A veces, un mecanismo similar es proporcionado por otros mecanismos.

Más claramente, la idea de que Python no es Java ilustra que la adición de campos en objetos y clases se realiza mediante la asignación habitual:

 def make_title(self): if self.title == 'Mister': return 'Mr. ' + self.surname class Person: pass john = Person() john.title = 'Mister' john.name = 'John' john.surname = 'Peterson' john.age = 33 Person.make_title = make_title print(john.make_title()) 

Recomendación general: no almacene tipos mutables como instancias de una clase, sin embargo, si sabe lo que está haciendo, utilice esta funcionalidad al máximo, lo principal es pensar detenidamente en todo al principio y documentar después.

Por ejemplo, es muy simple crear una clase que almacene enlaces a todas sus instancias:

 class RememberAll(): instances = [] def __init__(self): self.instances.append(self) a = RememberAll() b = RememberAll() print(RememberAll.instances) #-> [<__main__.RememberAll object at 0x7faa4a5ab7b8>, <__main__.RememberAll object at 0x7faa4a523c88>] 

Puede implementar la clase de algún objeto físico y, al cambiar sus características, invocar métodos para recalcular las características de otros elementos del sistema. O recuerde todos los controles deslizantes en el formulario y cuando cambie uno, mueva el resto automáticamente. No pretendo decir que una implementación de este tipo siempre es buena, pero a veces puede ser útil.

Bueno, desde que tocamos la física, quiero mencionar el operador @. Sí hay uno . Se introdujo para la multiplicación de matrices, que es la más divertida, pero parece que no se ha implementado para ninguno de los tipos de datos estándar, es decir, se introdujo originalmente solo para bibliotecas de terceros. Pero nada le impide agregar su soporte para sus tipos de datos mediante la implementación de los métodos __matmul__, __rmatmul__, __imatmul__

 class Person: def __init__(self, name): self.name = name def __matmul__(self, msg): return "@" + self.name + " " + msg john = Person("John") print(john @ "hello") # -> @John hello 

Source: https://habr.com/ru/post/es422311/


All Articles