• Generics in Python


    泛型(Generics)

    https://www.geeksforgeeks.org/generics-in-java/

    一般类的定义,其引用类是要在其代码中明确指定的

    但是对于一些上层公共逻辑,其期望可以应用到若干引用类中

    则定义泛型类, 可以满足这种需求。

    泛型类在使用的使用, 才绑定具体的引用类。

    Generics means parameterized types. The idea is to allow type (Integer, String, … etc., and user-defined types) to be a parameter to methods, classes, and interfaces. Using Generics, it is possible to create classes that work with different data types. An entity such as class, interface, or method that operates on a parameterized type is a generic entity.

    // Java program to show working of user defined
    // Generic classes
    
    // We use < > to specify Parameter type
    class Test<T> {
        // An object of type T is declared
        T obj;
        Test(T obj) { this.obj = obj; } // constructor
        public T getObject() { return this.obj; }
    }
    
    // Driver class to test above
    class Main {
        public static void main(String[] args)
        {
            // instance of Integer type
            Test<Integer> iObj = new Test<Integer>(15);
            System.out.println(iObj.getObject());
    
            // instance of String type
            Test<String> sObj
                = new Test<String>("GeeksForGeeks");
            System.out.println(sObj.getObject());
        }
    }

    Generics in Python

    https://textbooks.cs.ksu.edu/cc410/iii-web/20-extras/03-python-generics/

    如下,对于需要依赖的引用类, 定义类型变量 T

    然后再类定义时候, 指定其继承 Generic 类,指定T

    from typing import List, TypeVar, Generic
    
    
    T = TypeVar('T')
    
    class MyGenericList(Generic[T]):
    
        def __init__(self) -> None:
            self.__array: List[T] = list()
            
        def append(self, obj: T) -> None:
            self.__array.append(obj)
            
        def get(self, i: int) -> T:
            self.__array[i]
    generic_list: MyGenericList[Person] =  MyGenericList()
    
    person: Person = Person("Willie", 42)
    generic_list.append(person) 
    
    person_out: Person = generic_list[0]         # Properly Type Checked
    
    my_person_list.append("Test")                # TYPE CHECK ERROR

     

    typing.TypeVar

    https://docs.python.org/3/library/typing.html#typing.TypeVar

    在注解中, 你使用的类型一般是固定的, 是啥就写啥

    但是总有一些场景要求, 变量的类型是可变的, 这就引入了 类型变量。

    Type variables exist primarily for the benefit of static type checkers. They serve as the parameters for generic types as well as for generic function definitions. See Generic for more information on generic types. Generic functions work as follows:

    T = TypeVar('T')  # Can be anything
    S = TypeVar('S', bound=str)  # Can be any subtype of str
    A = TypeVar('A', str, bytes)  # Must be exactly str or bytes
    
    
    def repeat(x: T, n: int) -> Sequence[T]:
        """Return a list containing n references to x."""
        return [x]*n
    
    
    def print_capitalized(x: S) -> S:
        """Print x capitalized, and return x."""
        print(x.capitalize())
        return x
    
    
    def concatenate(x: A, y: A) -> A:
        """Add two strings or bytes objects together."""
        return x + y

    typing.Generic

    https://docs.python.org/3/library/typing.html#typing.Generic

    泛型基础类

    泛型类需要继承此基础类, 并定义类型变量, 这些类型变量类似函数的形参。

    Abstract base class for generic types.

    A generic type is typically declared by inheriting from an instantiation of this class with one or more type variables. For example, a generic mapping type might be defined as:

    class Mapping(Generic[KT, VT]):
        def __getitem__(self, key: KT) -> VT:
            ...
            # Etc.

    使用的时候, 先定义类型变量, 然后绑定Generic类,类似函数调用时候填充的实际参数。

    X = TypeVar('X')
    Y = TypeVar('Y')
    
    def lookup_name(mapping: Mapping[X, Y], key: X, default: Y) -> Y:
        try:
            return mapping[key]
        except KeyError:
            return default

    fastapi crud project application

    https://github.com/tiangolo/full-stack-fastapi-postgresql/blob/490c554e23343eec0736b06e59b2108fdd057fdc/%7B%7Bcookiecutter.project_slug%7D%7D/backend/app/app/crud/base.py

    from typing import Any, Dict, Generic, List, Optional, Type, TypeVar, Union
    
    from fastapi.encoders import jsonable_encoder
    from pydantic import BaseModel
    from sqlalchemy.orm import Session
    
    from app.db.base_class import Base
    
    ModelType = TypeVar("ModelType", bound=Base)
    CreateSchemaType = TypeVar("CreateSchemaType", bound=BaseModel)
    UpdateSchemaType = TypeVar("UpdateSchemaType", bound=BaseModel)
    
    
    class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
        def __init__(self, model: Type[ModelType]):
            """
            CRUD object with default methods to Create, Read, Update, Delete (CRUD).
            **Parameters**
            * `model`: A SQLAlchemy model class
            * `schema`: A Pydantic model (schema) class
            """
            self.model = model
    
        def get(self, db: Session, id: Any) -> Optional[ModelType]:
            return db.query(self.model).filter(self.model.id == id).first()
    
        def get_multi(
            self, db: Session, *, skip: int = 0, limit: int = 100
        ) -> List[ModelType]:
            return db.query(self.model).offset(skip).limit(limit).all()
    
        def create(self, db: Session, *, obj_in: CreateSchemaType) -> ModelType:
            obj_in_data = jsonable_encoder(obj_in)
            db_obj = self.model(**obj_in_data)  # type: ignore
            db.add(db_obj)
            db.commit()
            db.refresh(db_obj)
            return db_obj
    
        def update(
            self,
            db: Session,
            *,
            db_obj: ModelType,
            obj_in: Union[UpdateSchemaType, Dict[str, Any]]
        ) -> ModelType:
            obj_data = jsonable_encoder(db_obj)
            if isinstance(obj_in, dict):
                update_data = obj_in
            else:
                update_data = obj_in.dict(exclude_unset=True)
            for field in obj_data:
                if field in update_data:
                    setattr(db_obj, field, update_data[field])
            db.add(db_obj)
            db.commit()
            db.refresh(db_obj)
            return db_obj
    
        def remove(self, db: Session, *, id: int) -> ModelType:
            obj = db.query(self.model).get(id)
            db.delete(obj)
            db.commit()
            return 

    https://github.com/tiangolo/full-stack-fastapi-postgresql/blob/490c554e23343eec0736b06e59b2108fdd057fdc/%7B%7Bcookiecutter.project_slug%7D%7D/backend/app/app/crud/crud_item.py

    from typing import List
    
    from fastapi.encoders import jsonable_encoder
    from sqlalchemy.orm import Session
    
    from app.crud.base import CRUDBase
    from app.models.item import Item
    from app.schemas.item import ItemCreate, ItemUpdate
    
    
    class CRUDItem(CRUDBase[Item, ItemCreate, ItemUpdate]):
        def create_with_owner(
            self, db: Session, *, obj_in: ItemCreate, owner_id: int
        ) -> Item:
            obj_in_data = jsonable_encoder(obj_in)
            db_obj = self.model(**obj_in_data, owner_id=owner_id)
            db.add(db_obj)
            db.commit()
            db.refresh(db_obj)
            return db_obj
    
        def get_multi_by_owner(
            self, db: Session, *, owner_id: int, skip: int = 0, limit: int = 100
        ) -> List[Item]:
            return (
                db.query(self.model)
                .filter(Item.owner_id == owner_id)
                .offset(skip)
                .limit(limit)
                .all()
            )
    
    
    item = CRUDItem(Item)
  • 相关阅读:
    【转载】Android IntentService使用全面介绍及源码解析
    【转载】作为Android开发者,你真的熟悉Activity吗?
    【转载】从使用到原理学习Java线程池
    Linux 基础知识+常见命令
    Python中的字典合并
    Python的__hash__函数和__eq__函数
    C#中实现Hash应用
    深入理解python元类
    Docker搭建Gitlab服务器
    python的加密方式
  • 原文地址:https://www.cnblogs.com/lightsong/p/16868909.html
Copyright © 2020-2023  润新知