天天在写python,但是感觉自己对python的高级用法不是特别了解,此处浅析一下。
1 python类与对象
1.1 专业的类书写规范
类中比较专业的规范为:- 1 类属性
- 2 __init__初始化方法
- 3 实例属性
- 4 classmethod方法
- 5 staticmethod方法
- 6 私有方法
- 7 实例方法
- 1 classmethod方法涉及使用类中的资源
- 2 staticmethod方法一般用来实现固定的操作,一般不涉及类中的资源的操作。
class Student(object):
# 1 类属性
_ID_TYPE: str = "Student Person"
# 2 __init__初始化方法
def __init__(self, name, score, age):
# 3 实例属性
self._name: str = name
self._score: int = score
self._age: int = age
# 4 classmethod方法: 能操作类的全部资源
@classmethod
def get_student(cls):
return cls("tom", "100", 18)
# 5 staticmethod方法: 只能操作类的实例
@staticmethod
def print_student_type():
print(f"name is {Student._ID_TYPE}")
# 6 私有方法: 对外层用户透明
def _set_age(self, age):
if age > 100:
self._age = 100
elif age < 0:
self._age = 0
else:
self._age = age
# 7 实例方法
@property
def score(self):
return self._score
@score.setter
def score(self, score):
self._score = score
def set_age(self, age):
self._set_age(age)
1.2 类的私有成员保护
python实际上没有私有成员,大家公认的是实例或者类的私有成员(变量和方法)在前面加上下划线(IDE将不会帮助提示)。 如果类或者实例中的属性不设置私有,则其他程序员可以通过赋值的方式修改属性。 解决方法:将属性设置为私有属性,同时提供@proptity提供访问接口。 实现对私有成员的访问,同时不提供修改的策略。1.3 抽象类
抽象类继承abc.ABC,同时设置了@abstractmethod的方法子类必须重写。1.4 魔法方法
类的函数中左右两边都存在两个下划线的即为魔法方法。1.5 __str__和__repr__
student = Student.get_student() print(student)此时对象的print的结果就会去__str__函数进行处理。
student1 = Student.get_student() student2 = Student.get_student() print([student1, student2])在列表、元组、集合中打印的对象会去__repr__函数进行处理。
2 装饰器
装饰器分为两部分:- 1 装饰器的输入和输出
- 输入:oldFunction
- 输出:newFunction
- 2 装饰器的加工过程
- newFunction对oldFunction进行加工
2.1 不带参数的装饰器
- 1 装饰器输入一个旧函数,抛出一个新函数
- 2 装饰器在新函数中对旧函数进行加工
def robot(oldFunc):
def newFunc():
print("start")
oldFunc()
print("end")
return newFunc
@robot
def hello():
print("Hello World")
hello()
# start
# Hello World
# end
2.2 带参数的装饰器
- 1 装饰器输入一个旧函数,抛出一个新函数
- 2 装饰器在新函数中对旧函数进行加工
- 3 装饰器的新函数入口的参数设置与旧函数保持一致才能进行加工。
def robot(oldFunc):
def newFunc(name):
oldFunc(name[::-1])
return newFunc
@robot
def hello(name):
print(f"Hello {name}")
hello("alice")
# Hello ecila
2.3 多装饰器
多装饰器的执行顺序为离近原则,从离函数近到远的顺序执行装饰器。 例如,我们给出@runDouble, @logger装饰器.2.3.1 @logger @runDouble
def runDouble(oldFunc):
def newFunc(*args, **kwargs):
oldFunc(*args, **kwargs)
oldFunc(*args, **kwargs)
return newFunc
def logger(oldFunc):
def newFunc(*args, **kwargs):
print(f"===============")
oldFunc(*args, **kwargs)
print(f"===============")
return newFunc
@runDouble
@logger
def hello(name):
print(f"Hello {name}")
hello("alice")
# ===============
# Hello alice
# ===============
# ===============
# Hello alice
# ===============
2.3.2 @runDouble @logger
def runDouble(oldFunc):
def newFunc(*args, **kwargs):
oldFunc(*args, **kwargs)
oldFunc(*args, **kwargs)
return newFunc
def logger(oldFunc):
def newFunc(*args, **kwargs):
print(f"===============")
oldFunc(*args, **kwargs)
print(f"===============")
return newFunc
@logger
@runDouble
def hello(name):
print(f"Hello {name}")
hello("alice")
#===============
# Hello alice
# Hello alice
# ===============
2.4 双重装饰器(带括号)
双重装饰器(带括号)实际上就是可以等同于使用两次@装饰器修饰. 双重装饰器的实现需要使用2次函数嵌套,具体如下:
def fun(type):
if type == "double":
def runDouble(oldFunc):
def newFunc(*args, **kwargs):
oldFunc(*args, **kwargs)
oldFunc(*args, **kwargs)
return newFunc
return runDouble
elif type == "logger":
def logger(oldFunc):
def newFunc(*args, **kwargs):
print(f"===============")
oldFunc(*args, **kwargs)
print(f"===============")
return newFunc
return logger
@fun("double")
def hello(name):
print(f"Hello {name}")
hello("alice")
# Hello alice
# Hello alice
3 浅拷贝与深拷贝
3.1 普通赋值
a = [1, 2, 3] b = a 修改a,则b也会跟着修改。 因为a,b都指向同一个对象,即指向同一块内存地址。a = [1, 2, 3]
b = a
a[0] = 4
print(a, b)
# [4, 2, 3] [4, 2, 3]
3.2 浅拷贝
3.2.1 不带子对象的浅拷贝
a = [1, 2, 3] b = a.copy() 修改a,b不会跟着修改。 b为一个新的对象,拷贝了a的父对象。a = [1, 2, 3]
b = a.copy()
a[0] = 4
print(f"a is {a} b is {b}")
# a is [4, 2, 3] b is [1, 2, 3]
3.2.2 带子对象的浅拷贝
a = [1, 2, [3, 4]] b = a.copy() 修改a[2]中的列表值,b跟着修改。 b虽然为一个新的对象,拷贝了a的父对象,但是不会拷贝子对象[3, 4].a = [[1, 4, 5], 2, 3]
b = a.copy()
a[0][0] = 9
print(f"a is {a} b is {b}")
# a is [[9, 4, 5], 2, 3] b is [[9, 4, 5], 2, 3]
3.3 深拷贝
from copy import deepcopy a = [1, 2, [3, 4]] b = deepcopy(a) 修改a[2]的列表,b不发生改变。 b拷贝了a的父对象和子对象。import copy
a = [[1, 4, 5], 2, 3]
b = copy.deepcopy(a)
a[0][0] = 9
print(f"a is {a} b is {b}")
# a is [[9, 4, 5], 2, 3] b is [[1, 4, 5], 2, 3]
4 如何多层跳出循环
众所周知,break只能跳出一层循环,如果遇到多层循环该如何直接退出到最外层循环呢。4.1 try except
最推荐使用的一种方法,无论在多少层for之中,最内层抛出一个raise给except接受即可。try:
for i in range(10):
for j in range(10):
print(f"i is {i} j is {j}")
if (i == j == 2):
raise "i,j已经满足要求了"
except Exception as e:
print(e)
4.2 for else continue
不太推荐使用,遇到多个for则需要写多个else: continue break else在这里处于一种语法糖一样的东西- 1 当for循环执行成功,则执行else中的语句
- 2 当for循环执行不成功,则跳过else中的语句。
- 3 此时,当时for循环中遇到break,则跳过else中的continue,继续执行break。
for i in range(10):
for j in range(10):
print(f"i is {i} j is {j}")
if (i == j == 2):
break
else:
continue
break
5 any和all
5.1 简易使用
any:列表中有一个为True,则返回True all:列表中有一个为False,则返回Falseprint(any([True, False, True, False]))
print(all([True, False, True, False]))
# True
# False
5.2 搭配列表使用
判断一个列表中是否存在能整除2的数。x = [1, 2, 3, 4, 5, 6]
print(any([i%2==0 for i in x]))