🍰
Grasshopper ES por BetweenRealities
  • Using and Generating Documentation
    • GitHub
    • Discord
      • Speckle Webhooks
    • Speckle Client
  • Potencial technological implementations
  • 🧞Compute
    • Introducción a Grasshopper
      • Customizar Entorno
        • VSCode
      • Rhinoceros 3d
      • Hops
      • Galapagos
    • Modelos Informados
      • Comportamiento Estructural
        • Automatizar cálculo Python
      • OOP
      • Rhino Inside Revit
        • Revit
          • Modelado 3d en Revit
          • Certificación profesional Revit
      • Energía
    • Procesos Urbanos
      • Automatizar Qgis
      • Librerías Python
      • Librerías Grasshopper
      • Stable Diffusion
    • Programación
      • RhinoPython
        • Anatomía del script
        • Python básico
        • Tuples, listas y diccionarios
        • Operadores y funciones
        • Ejecución condicional
        • Geometría
        • Clases
      • Multithread
  • 🪅Database
    • Lenguaje Python
      • Types and operations
      • Statements and syntax
      • Function and generators
      • Modules and packages
      • Classes and OPP
      • Exception and tools
      • Advance topics
    • Análisis de la Información
      • Comparison with SQL
      • Comparison with R / R libraries
      • Pandas
    • Abrir Acceso
      • Rest API Abierta
    • Blockchain Descentralización
  • 🕸️COLLECT
    • Captura de Datos
      • Raspberry Pi
        • Encendido y apagado automático
      • Arduino
      • UAS
      • Fotogrametría
        • Crashes
    • Técnicas Machine Learning
      • Clasificación
      • Computer Vision
    • Computación en la Nube
      • Contenedores
      • Azure
      • Ubuntu Server Deploy
      • PostgreSQL Server
      • Rhino Compute Deploy
  • 🍭INTERACT
    • Introducción a Unreal Engine
      • Ejecutar Python
      • Datasmith
      • Materiales
        • Crear PBR
        • Materiales Introducción
      • Iluminación
        • Iluminación Introducción
        • Raytraced Iluminación Cinemática
      • Assets Management
    • Interacción Inmersiva
      • Blueprints
        • Blueprints estandar
        • Blueprints Introducción
        • Diseño Nivel
      • Packaging
      • Performance
    • Interfaces Bidimensionales
Con tecnología de GitBook
En esta página

¿Te fue útil?

  1. Database
  2. Lenguaje Python

Classes and OPP

Classes and OPP

  • OOP: Why use classes; OOP from 30k feet.

Main point of OOP: code reuse. Inheritance search look for an attribute: from bottom to top of the object tree and from left to right. Difference between a class object and an instance object: both are namespace (packages of variables that appear as attributes); difference is that classes creates instances. First argument in a class's method: self by convention; receives the instance object; designed to process or change objects. init method use for: constructor method; it is passed the new instance implicitly and any argument explicitly; most commonly used operator overloading method. Specify a class's superclasses: listing them in parentheses in the class statement after the new class's name.

  • Class coding basics: Classes generate multiple instance objects; Classes are customized by inheritance; Classes can intercept python operators.

How are classes related to modules?: classes are statements not entire files; module is like a single instance class (without inheritance). How and where are class attributes created?: assigning attributes to a class object. How and where are instance attributes created?: assigning attributes to a class object. How is operator overloading coded in a class?: begin and end with double underscores; runs them automatically when an instance appear in the corresponding operation. When might you want to support operator overloading?: for mimic the built-in's. Key concepts to understand OOP. self and init.

  • A more realistic example: Making instance; Adding behavior methods; Operator overloading; Customizing behavior by subclassing; Customizing constructors, too; Using introspection tools; Storing objects in a database; Future directions. We took objects created by our classes and made them persistent by storing them on a shelve object db.

Importance of move processing into methods instead of hardcoding: only change one (code maintenance, avoid redundancy), so the method can be run on any instance (encapsulation). Why customize by subclassing rather than copying the original and modifying?: extend our prior work with custom stuff. Why call back to a superclass to run default actions, instead of coding and modifying its code in a subclass?: if a subclass needs to perform default actions coded in a superclass method then call back it (avoid redundancy). Why is it better to use tools like dict that allow objects to be processed generically than to write more custom code for each type of class?: repr not be updated each time a new attribute is added to instances in an init constructor.

  • Class coding details: The class statement; Methods; Inheritance; Namespaces; Documentation strings; Classes versus modules.

What is an abstract superclass?: class that callas a method but does not inherit or define it; this if often used as a way to generalize classes when behavior cannot be predicted until a more specific sub-class. Why might a class need to manually call the init method in a superclass?. Augmenting an inherited method: to augment you have to redefine it in a subclass, but call back to the superclass's of the method; pass the self instance to the superclass's on the method manually (subclass.method(self,...)). How does a class's local scope differ from that of a function: Like modules, the class local scope morphs into an attribute namespace after the class statement is run.

  • Operator overloading: Indexing and slicing; Iterable objects; Index iteration; Membership; Attributes access; String representation; Right-side and in-place uses; call expressions; Comparisons; Boolean tests; Object destruction.

> Operator overloading methods to support iteration in your classes. Operators overloading methods handle printing and in what context?. How to intercept slice operations in a class?. How can you catch in-place addition in a class?. When should you provide operator overloading?.

  • Design with classes: Python and OOP; OOP and inheritance; OOP and composition; OOP and delegation; Pseudoprivate class attributes; Methods are objects; Multiple inheritance; Other design-related topics.

Multiple inheritance: class inherits from more than one superclass; mixing together multiples packages of class-based code. Delegation: wrap an object in a proxy class. Composition: controller class embeds and directs a number of objects and provides an interface all its own. Bound methods: combine an instance and a method function; you can call them without passing in an instance object (original instance is still available). Pseudoprivate attributes: name begin with '__' are used to localize names to the enclosing class

  • Advance class topics: Extending built-in types; New style class model;/changes; /extensions; /methods; Decorators and metaclasses; The super built-in function; Class gotchas.

What are function and class decorators?: function decorators are generally used to manage a function or method, or add to it a layer of logic that is run each time the function or method is called (can be used to log, count calls, check argument types, declare static methods, class methods and properties); class decorators similar but manage whole objects and their interfaces instead of a function call.

> Code a new-style class:: search the diamond pattern of multiple inheritance trees differently. Difference between classic a new-style classes. Normal and static methods. slots and super valid to use?.


#%%ho

sequence = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def multiply_by_2(item):
    return item * 2

mapped = map(multiply_by_2, sequence)
list(mapped)

def multipley(args):
    total = 1
    for arg in args:
        total = total * arg
    return total

multipley(args=sequence)

list(map(lambda item: item * 2, sequence))



#%%
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def __str__(self):  # for print function to work with this class object
        return f"{self.name} is {self.age} years old."


bob = Person('Bob', 35)
print(bob)

#%%
# class test with instance method, classmethod and staticmethod
class ClassTest():
    def instance_method(self):  # instance method
        print(f"This is an instance method {self}")
    
    @classmethod
    def class_method(cls):  # cls is the class itself
        print(f"This is a class method {cls}")
        
    @staticmethod
    def static_method():    # no access to the class or instance
        print("This is a static method")
        
test = ClassTest()
ClassTest().class_method()
ClassTest().instance_method()
ClassTest().static_method()


# create a class with a cuple of class methods + static methods
class Book():
    TYPES = ('hardcover', 'paperback')
    
    def __init__(self, name, book_type, weight): # constructor method for the class Book with 3 arguments (name, book_type, weight)
        self.name = name
        self.book_type = book_type
        self.weight = weight
    
    def __repr__(self):
        return f"<Book {self.name}, {self.book_type}, weighing {self.weight}g>"
    
    @classmethod
    def hardcover(cls, name, page_weight): # cls is the class itself (Book)
        return cls(name, cls.TYPES[0], page_weight + 100)
    
    @classmethod
    def paperback(cls, name, page_weight):   # cls is the class itself (Book)
        return cls(name, cls.TYPES[1], page_weight)
    
    @staticmethod  # no access to the class or instance (Book) or self
    def book_type_weight(weight):
        return weight * 0.5
    
Book.hardcover('Harry Potter', 1500)


#%% Inheritance
class Device(): # parent class (superclass) with 2 methods (on and off) and 2 attributes (name and connected_by) 
    def __init__(self, name, connected_by):
        self.name = name
        self.connected_by = connected_by
        self.connected = True
        
    def __str__(self):
        return f"Device {self.name!r} ({self.connected_by})"
    
    def disconnect(self):  # instance method
        self.connected = False
        print("Disconnected.")
        
printer = Device("Printer", "USB")
print(printer)
printer.disconnect()


class Printer(Device):  # Printer class inherits from Device class (Printer is a Device)
    def __init__(self, name, connected_by, capacity): # constructor method for the class Printer with 3 arguments (name, connected_by, capacity)
        super().__init__(name, connected_by)     # super() is the parent class (Device) and it's constructor method (Device.__init__) is called with the arguments (name, connected_by) 
        self.capacity = capacity    # self.capacity is an attribute of the class Printer
        self.remaining_pages = capacity    # self.remaining_pages is an attribute of the class Printer
        
    def __str__(self):
        return f"{super().__str__()} ({self.remaining_pages} pages remaining)"  # super().__str__() calls the __str__ method of the parent class (Device) and returns the string representation of the parent class (Device)
    
    def print(self, pages):
        if not self.connected:
            print("Your printer is not connected!")
            return
        print(f"Printing {pages} pages.")
        self.remaining_pages -= pages   # self.remaining_pages is an attribute of the class Printer and it's value is reduced by the number of pages printed   

printer = Printer("Printer", "USB", 500)
printer.print(20)
printer.disconnect()


#%% Composition 
class BookShelf():  # parent class (superclass) with 1 method (__init__) and 1 attribute (number_of_books)
    def __init__(self, *books): # constructor method for the class BookShelf with 1 argument (*books) which is a tuple of books (Book objects)
        self.books = books
        
    def __str__(self):
        return f"BookShelf with {len(self.books)} books."
    
    
class Book(): # parent class (superclass) with 2 methods (__init__) and 2 attributes (name and book_type)
    def __init__(self, name):
        self.name = name
        
    def __str__(self):
        return f"Book {self.name}"
    
    
book = Book("Harry Potter")
book2 = Book("Python 101")
shelf = BookShelf(book, book2)

#%% First class functions
def divide(dividend, divisor):  # function divide   
    if divisor == 0:
        raise ZeroDivisionError("Divisor cannot be 0.") # raise an exception    
    return dividend / divisor

def calculate(*values, operator):   # function calculate with 2 arguments (*values and operator)
    return operator(*values)

result = calculate(20, 4, operator=divide)  # operator=divide is a keyword argument and divide is a function    
print(result)


# Usefull functions for lists  
def search(sequence, expected, finder): 
    for elem in sequence:
        if finder(elem) == expected:
            return elem
    raise RuntimeError(f"Could not find an element with {expected}.")

friends = [
    {"name": "Rolf Smith", "age": 24},
    {"name": "Adam Wool", "age": 30},
    {"name": "Anne Pun", "age": 27}
]

def get_friend_name(friend):
    return friend["name"]

print(search(friends, "Rolf Smith", get_friend_name))   
print(search(friends, "Adam Wool", lambda friend: friend["name"]))  # lambda function is used instead of get_friend_name function


#%% Simple decorator
import functools

def make_secure(func):  # function make_secure with 1 argument (func) which is a function get_admin_password
    @functools.wraps(func)  # functools.wraps is used to preserve the metadata of the function get_admin_password
    def secure_function():  # secure_function is a wrapper function for the function func   
        if user["access_level"] == "admin":
            return func()   # func() is the function func   
        else:
            return f"No admin permissions for {user['username']}."
    return secure_function  # return the function secure_function       

@make_secure # make_secure is a decorator for the function get_admin_password 
def get_admin_password():   # function get_admin_password    
    return "1234"


# get_admin_password = make_secure(get_admin_password)  # get_admin_password is a function and it's value is the function secure_function which is returned by the function make_secure with the argument get_admin_password
user = {"username": "jose", "access_level": "admin"}
print(get_admin_password())  # secure_function() is called
print(get_admin_password.__name__)  # secure_function is the name of the function get_admin_password


#%% Decorator functions with parameters
def make_secure(func):  # function make_secure with 1 argument (func) which is a function get_admin_password
    @functools.wraps(func)  # functools.wraps is used to preserve the metadata of the function get_admin_password
    def secure_function(*args, **kwargs):  # secure_function is a wrapper function for the function func   
        if user["access_level"] == "admin":
            return func(*args, **kwargs)   # func() is the function func   
        else:
            return f"No admin permissions for {user['username']}."
    return secure_function  # return the function secure_function

@make_secure # make_secure is a decorator for the function get_admin_password
def get_admin_password(panel):   # function get_admin_password
    if panel == "admin":
        return "1234"
    elif panel == "billing":
        return "super_secure_password"
    
print(get_admin_password("billing"))  # secure_function() is called


#%% Decorator with parameters

user = {"username": "jose", "access_level": "guest"}


def make_secure(access_level):  # function make_secure with 1 argument (access_level)
    def decorator(func):  # create a decotator. Function decorator with 1 argument (func) which is a function get_admin_password 
        @functools.wraps(func)  # functools.wraps is used to preserve the metadata of the function get_admin_password
        def secure_function(*args, **kwargs):
            if user["access_level"] == access_level:
                return func(*args, **kwargs)
            else:
                return f"No {access_level} permissions for {user['username']}."
        return secure_function
    return decorator
 
 
@make_secure("admin") # make_secure is a decorator for the function get_admin_password 
def get_admin_password():   # function get_admin_password
    return "1234"


@make_secure("guest") # make_secure is a decorator for the function get_dashboard_password
def get_dashboard_password():   # function get_dashboard_password
    return "user_password"

print(get_admin_password())  # secure_function() is called
print(get_dashboard_password())  # secure_function() is called


#%% Custom errors
class TooManyPagesReadError(ValueError):  # class TooManyPagesReadError is a subclass of the class ValueError
    pass


class Book():
    # init method with name, page_count and pages_read attributes
    def __init__(self, name, page_count, pages_read):
        self.name = name
        self.page_count = page_count
        self.pages_read = 0
        
    def __repr__(self):
        return f"<Book {self.name}, read {self.pages_read} pages out of {self.page_count}>"  # return a string representation of the object 
    
    def read(self, pages:int):  # method read with 1 argument (pages)   
        if self.pages_read + pages > self.page_count:  # if the number of pages read is greater than the number of pages in the book
            # raise ValueError(f"You tried to read {self.pages_read + pages} pages, but this book only has {self.page_count} pages.")  # raise an exception 
            raise TooManyPagesReadError(f"You tried to read {self.pages_read + pages} pages, but this book only has {self.page_count} pages.")  # raise an exception with a custom error

python101 = Book("Python 101", 50, 0)  # create an object python101 from the class Book
try:
    python101.read(35)  # call the method read with 1 argument (35)
    python101.read(50)  # call the method read with 1 argument (50)
    
except TooManyPagesReadError as e:
    print(e)


#%% Decorators simple example

def decorator_function(original_function):  # function decorator_function with 1 argument (original_function)
    def wrapper_function(*args, **kargs): # function wrapper_function 
        print(f"wrapper executed this before {original_function.__name__}")  # print a string
        return original_function(*args, **kargs)  # return the function original_function
    return wrapper_function


class decorator_class(object):  # class decorator_class 
    def __init__(self, original_function):  # init method with 1 argument (original_function)
        self.original_function = original_function  # attribute original_function
    
    def __call__(self, *args, **kwargs): # method __call__ with 2 arguments (args and kwargs) 
        print(f"call method executed this before {self.original_function.__name__}") 
        return self.original_function(*args, **kwargs)
     
        

def display():  # function display
    print("display function ran")

# Using function decorator ------------------------------------------
@decorator_function  # decorator_function is a decorator for the function display
def displayother():  # function display
    print("display function ran another function")
    
@decorator_function  # decorator_function is a decorator for the function display
def display_info(name, age):  # function display_info with 2 arguments (name, age)
    print(f"display_info ran with arguments ({name}, {age})")    
    

# Using class decorator ------------------------------------------
@decorator_class  # decorator_function is a decorator for the function display
def displayother():  # function display
    print("display function ran another function")
    
@decorator_class  # decorator_function is a decorator for the function display
def display_info(name, age):  # function display_info with 2 arguments (name, age)
    print(f"display_info ran with arguments ({name}, {age})")    
    
    
decorated_display = decorator_function(display)()  # decorated_display is a function and it's value is the function wrapper_function which is returned by the function decorator_function with the argument display
displayother()  # call the function displayother which is decorated by the decorator decorator_function 
display_info('John', 25)  # call the function display_info which is decorated by the decorator decorator_function


#%% Practical example of decorators
import functools

def my_logger(orig_func):  # function my_logger with 1 argument (orig_func)
    import logging  # import the module logging
    # set the basic configuration of the logging module
    logging.basicConfig(
        filename=f'{orig_func.__name__}.log', level=logging.INFO) # set the filename and the level of logging 

    # functools.wraps is used to preserve the metadata of the function orig_func
    @functools.wraps(orig_func)
    def wrapper(*args, **kwargs):  # function wrapper with 2 arguments (args and kwargs)
        # log a message
        logging.info(f'Ran with args: {args}, and kwargs: {kwargs}')
        return orig_func(*args, **kwargs)  # return the function orig_func
    return wrapper


def my_timer(orig_func):  # function my_timer with 1 argument (orig_func)
    import time

    # functools.wraps is used to preserve the metadata of the function orig_func
    @functools.wraps(orig_func)
    def wrapper(*args, **kwargs):  # function wrapper with 2 arguments (args and kwargs)
        t1 = time.time()  # get the current time
        result = orig_func(*args, **kwargs)  # return the function orig_func
        t2 = time.time() - t1  # get the current time and subtract the time t1
        print(f'{orig_func.__name__} ran in: {t2} sec')  # print a string
        return result  # return the result of the function orig_func
    return wrapper

@my_logger
def display_info(name, age):  # function display_info with 2 arguments (name, age)
    print(f"display_info ran with arguments ({name}, {age})")

import time    
@my_timer # decorator my_timer is a decorator for the function display_info_sleep
def display_info_sleep(name, age):  # function display_info with 2 arguments (name, age)
    time.sleep(1)
    print(f"display_info ran with arguments ({name}, {age})")
    
    
display_info('John', 25)  # call the function display_info which is decorated by the decorator my_logger
display_info_sleep('Wick', 40)


#%% Change decorators together
from functools import wraps

def my_logger(orig_func):  # function my_logger with 1 argument (orig_func)
    import logging  # import the module logging
    # set the basic configuration of the logging module
    logging.basicConfig(
        filename=f'{orig_func.__name__}.log', level=logging.INFO) # set the filename and the level of logging 

    # functools.wraps is used to preserve the metadata of the function orig_func if not used the function display_info will have the name wrapper
    @wraps(orig_func)
    def wrapper(*args, **kwargs):  # function wrapper with 2 arguments (args and kwargs)
        # log a message
        logging.info(f'Ran with args: {args}, and kwargs: {kwargs}')
        return orig_func(*args, **kwargs)  # return the function orig_func
    return wrapper


def my_time(original_function):  # function my_time with 1 argument (original_function)
    import time

    @wraps(original_function)
    def wrapper(*args, **kwargs):  # function wrapper with 2 arguments (args and kwargs)
        t1 = time.time()  # get the current time
        result = original_function(*args, **kwargs)  # return the function original_function
        t2 = time.time() - t1  # get the current time and subtract the time t1
        print(f'{original_function.__name__} ran in: {t2} sec')  # print a string
        return result  # return the result of the function original_function
    return wrapper

@my_logger
@my_time
def display_info(name, age):  # function display_info with 2 arguments (name, age)
    time.sleep(1)
    print(f"display_info ran with arguments ({name}, {age})")


display_info('John', 25)  # call the function display_info which is decorated by the decorator my_logger
AnteriorModules and packagesSiguienteException and tools

Última actualización hace 2 años

¿Te fue útil?

🪅