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