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 工厂模式
网友评论