前置知识
class Person:
amount = 0
def __init__(self):
Person.amount += 1 # 若想要在函数中使用类变量,需要在前面加上类名,否则就是局部变量了
self.name = 'mike'
print('aa')
1.魔法方法
class vector:
def __init__(self, x, y): # 构造函数
self.x = x
self.y = y
def __del__(self): # 析构函数
print('Already deled')
def __add__(self, other):
return vector(self.x + other.x, self.y + other.y)
def __repr__(self):
return f'x: {self.x}, y: {self.y}'
def __len__(self):
return 10
def __call__(self, *args, **kwargs):
print('just called')
v1 = vector(1, 2)
v2 = vector(3, 4)
v3 = v1 + v2
print(v3) # 调用__repr__函数
print(v3()) # 调用__call__函数
2.装饰器
装饰器是一个函数,输入一个函数,返回增加了其他功能的另一个函数。
def decorator(function): # 传入一个函数,传出一个函数
a = 1
def wrapper(*args, **kwargs):
print(f'already decorated!{a}')
function(*args, **kwargs)
return wrapper
@decorator
def hello(name):
print(f'hello,{name}')
hello('mike')
# already decorated!1
# hello,mike
实际应用:
import time
def run_time(function):
def wrapper(*args, **kwargs):
before = time.time()
re_val = function(*args, **kwargs)
after = time.time()
fname = function.__name__
print(f'{fname} has run {after-before}!')
return re_val
return wrapper
@run_time # 计算函数执行用时
def add(a, b):
return a + b
print(add(1, 2))
3.生成器
yield
4.参数解析(Parsing)
在终端的控制台中输入参数传入py文件中。
def main(*args, **kwargs):
print(args[0])
print(args[1])
print(kwargs['KEYONE'])
print(kwargs['KEYTWO'])
if __name__ == '__main__':
main(1, '222', 'SSS', KEYONE='QQQQ', KEYTWO='EEE')
与c语言main的参数一样,可以从命令行中传入参数。
import sys
filename = sys.argv[0]
print(filename)
5.封装(Encapsulation)
绑定属性有两种方式,:
- 通过“实例.属性”。优点:简单;缺点:直接暴露、无法进行参数检查等。如:
s = Student()
s.score = 9999
- 通过设置类方法进行绑定。优点:没有直接暴露、可以进行参数检查;缺点:调用不简单,如:
class Person:
def __init__(self, name, age, gender):
self.__name = name # 私有属性
self.__age = age
self.__gender = gender
def show_private(self): # 对象的私有属性可以通过函数获取 getter
return self.__name
def modify_private(self, newname): # 对象的私有属性可以通过函数更改 setter
self.__name = newname
上述造成了一些问题,即之前使用该类实例化的所有对象均要更改代码。
- 而@property综合了两种优点:既能参数检查,还能类似于访问属性那样进行绑定。故使用@property对函数进行装饰,从而实现以上的优点。
class 类名(object):
@property
def 函数名(self):
return self._函数名 #例如函数名是score,属性名则为_score,这样目的是属性设置为私有属性,且函数名到时类似于属性调用 时便于理解,例如s.score = 99 一看就知道是在设置分数,但我们要理解的时此时并非是访问属性,本质是在调用函数
@函数名.setter
def 函数名(self, value):
if 参数检查:
raise 错误
self._函数名 = value
class Person:
def __init__(self, name, age, gender):
self.__name = name # 私有属性
self.__age = age
self.__gender = gender
@property
def name(self): # getter函数上加@property修饰器
return self.__name
@name.setter
def name(self, newname): # setter函数与getter函数重名且加上函数名.setter修饰器
self.__name = newname
p1 = Person('Mike', 18, 'man')
p1.name = 'achao' # 可以通过赋值改变属性
print(p1.name) # 通过.查看属性
属性的方法名不要和实例变量重名。例如,以下的代码是错误的:
class Student(object):
# 方法名称和实例变量均为birth:
@property
def birth(self):
return self.birth