pythonic

作者: 山猪打不过家猪 | 来源:发表于2023-01-28 17:50 被阅读0次

    1.下划线的用法

    • 只在类的内部使用双下划线


      image.png
    • 只在模块内使用单下划线(外部import不了)


      image.png
    • 忽略不重要的值,单下划线代替


      image.png

    2.字典的方法

    2.1字典处理缺失键
    • 设置默认值
    dict_ = {"a":100,"b":200}
    print(dict_.get("c",0))
    
    • 使用defaultdict
    from collections import defaultdict
    
    my_dict = defaultdict(list)
    my_dict["a"].append(1)
    my_dict["a"].append(2)
    my_dict["a"].append(3)
    print(my_dict['a'])
    >>>
    [1,2,3]
    
    2.2字典推导式
    • 未使用
    class Student:
        def __init__(self,name,age,email) -> None:
            self.name = name
            self.age =age
            self.email = email
    
    list_stu = [Student("kiwi",20,"kiwi@kiwi.com"),Student("fxx",17,"fxx@fxx.com")]
    # my function
    emails_for_students={}
    for stu in list_stu:
        if stu.email:
            emails_for_students[stu.name] = stu.email
    
    print(emails_for_students)
    >>>
    {'kiwi': 'kiwi@kiwi.com', 'fxx': 'fxx@fxx.com'}
    
    • 使用推导式
    from collections import defaultdict
    
    class Student:
        def __init__(self,name,age,email) -> None:
            self.name = name
            self.age =age
            self.email = email
    
    list_stu = [Student("kiwi",20,"kiwi@kiwi.com"),Student("fxx",17,"fxx@fxx.com")]
    # my function
    emails_for_students={stu.name:stu.email for stu in list_stu if stu.email}
    print(emails_for_students)
    >>>
    {'kiwi': 'kiwi@kiwi.com', 'fxx': 'fxx@fxx.com'}
    
    2.3合并字典

    ChainMap合并后,类似于做了差集,且以第一个为准

    from collections import ChainMap
    
    m1 = {"a":1,"b":2,"c":3}
    m2 = {"v":100,"d":2,"a":3}
    m3 = {"q":100,"w":2,"e":3}
    
    bb = ChainMap(m2,m1,m3)
    print(bb['a'])
    >>>
    3
    

    3.面向对象

    3.1 类方法及继承
    class Employee:
        MIN_SALAT = 30000
        def __init__(self,name,salary=30000) -> None:
            self.name = name
            self.salary = salary
    
        @classmethod
        def from_file(cls,filename):
            with open(filename,"r") as f:
                name = f.readline()
            return cls(name)
    
        def sayHello(self):
            return f"hello {self.name}"
    
    
    class Manager(Employee):
        MIN_SALAT = 30000
        def __init__(self,name,car,salary=30000) -> None:
            Employee.__init__(self,name)
            self.car = car
            self.salary = salary
    
        @classmethod
        def from_file(cls,filename):
            with open(filename,"r") as f:
                ame = f.readline()
            return cls(Manager.name)
    
        def sayHello(self):
            return f"hello {self.name}"
    
    
    file_name = Employee.from_file("employee_name.txt")
    print(file_name.sayHello())
    print(file_name.salary)
    
    manager_name = Manager("GJJ","BENZ",90000)
    print(manager_name.sayHello())
    print(manager_name.salary)
    >>>
    hello Fxx Peng
    30000
    hello GJJ
    90000
    
    3.2自定义可迭代对象
    
    from datetime import timedelta,date
    
    class DateRange:
        def __init__(self,first_dt,last_dt) -> None:
            self.first_dt = first_dt
            self.last_dt =last_dt
            self._current_dt  = first_dt
        
        def __iter__(self):
            print("返回自己")
            return self
    
        def __next__(self):
            print("判断循环")
            if self._current_dt >= self.last_dt: #判断当前循环和终止条件
                raise StopIteration
            current_dt = self._current_dt
            self._current_dt = timedelta(days=1)
            return current_dt
        
    for day in DateRange(date(2022,6,1),date(2022,9,2)):
        print(day)
    
    3.3自定义容器对象

    常用容器set list dict tupple

    class Product:
        def __init__(self,name:str,price:float,spec_num:int) -> None:
            self.name = name
            self.price = price
            self.spec_num = spec_num  #促销编号
    
    
    class Promotion:
        """
        传入价格区间,不同区间rate不一样
        """
        def __init__(self,lower_num:int,upper_num:int,rate:float) -> None:
            self.__lower_num = lower_num
            self.__upper_num =upper_num
            self.__rate = rate
        
        @property
        def rate(self)->float:
            return self.__rate
        
        def __contains__(self,product:Product)->bool:
            return self.__lower_num<=product.spec_num<= self.__upper_num
    
    
    def get_total_price(products,promotions)->float:
        _total_price =0
        for product in products:
            promotion = [promotion for promotion in promotions if product in promotion][0] #容器用法
            _total_price += product.price * promotion.rate
        return _total_price 
    
    
    top_promotion = Promotion(100,199,0.5)
    average_promotion = Promotion(50,99,0.8)
    none_promotion = Promotion(0,49,1)
    promotions1 = (top_promotion,average_promotion,none_promotion)
    products2 = [Product('cart',1999.9,188),Product('computer',5999.9,88),Product('toy',22.5,33)]
    
    total_price = get_total_price(products2,promotions1)
    print(total_price)
    
    • 不使用对象容器


      image.png
    3.4 动态处理属性
    • __getattr__:控制了没有定义的属性(调用属性)
      例子中name 和age都赋值过所以存在,但是nickname没有,所以输出了get attribute nickname
    
    class Person:
        def __init__(self,name:str) -> None:
            self.name = name
        
        def __getattr__(self,attr):
            print("get attribute",attr)
        
    
    person = Person("Steven")
    person.age = 13
    print(person.name,person.age,person.nickname)
    print(person.__dict__)
    >>>
    get attribute nickname
    Steven 13 None
    {'name': 'Steven', 'age': 13}
    
    • __getattribute__:控制所有属性的生成(调用属性)
      虽然这种方法可以用于属性的控制,但是会很乱
    class Person:
        def __init__(self,name:str) -> None:
            self.name = name
        
        def __getattribute__(self,attr):
            print("##get attribute##",attr)
            if attr in ('age','name'): #过滤
                return 2 * super().__getattribute__(attr)
            return super().__getattribute__(attr) #调用父类的getattribute
    
    person = Person("Steven")
    person.age = 13
    print(person.name,person.age)
    print(person.__dict__)
    >>>
    ##get attribute## name
    ##get attribute## age
    StevenSteven 26 #都乘2
    ##get attribute## __dict__
    {'name': 'Steven', 'age': 13}
    
    • 正确控制属性生成
    class Context:
        """
        权限控制的上下文
        """
        def __init__(self,user:str,roles) -> None:
            self.user = user
            self.roles = set(roles)
        
        def has_permission(self,role:str) -> bool:
            return role in self.roles
        
        def get_permission(self,role:str)->None:
            self.roles.add(role)
    
    
    class Project:
        def __init__(self,name:str,price:float,context:Context) -> None:
            self.name = name
            self.price = price
            self.context = context
    
        def __getattribute__(self, attr: str):
            if attr == "price":
                if self.context.has_permission("owner"):
                    return super().__getattribute__(attr)
                else:
                    raise AttributeError(f"访问‘{attr}’失败.")
            return super().__getattribute__(attr)
    
    
    context = Context("fxx",["user","admin"])
    pro1 = Project("big project",16999.0,context)
    print(pro1.name)
    print(pro1.price)
    >>>
    AttributeError: 访问‘price’失败. #不是owner访问失败
    
    • 添加权限
    
    context = Context("fxx",["user","admin"])
    pro1 = Project("big project",16999.0,context)
    context.set_permission('owner') #这里不需要要调整位置设置,因为在pro1设置时有getattribute
    print(pro1.price)
    >>>
    16999.0
    
    3.5 工厂模式

    相关文章

      网友评论

          本文标题:pythonic

          本文链接:https://www.haomeiwen.com/subject/gltuhdtx.html