您的位置:首页 > 编程语言 > Python开发

Python学习第十三天——装饰器和继承

2018-03-12 18:23 405 查看

上周回顾

#关键字参数**kwargs - 根据参数名来决定如何执行

def say_hello(*args, **kwargs):
print(args)#相当于元组(可变参数)
print(kwargs)#相当于字典(关键字参数)
say_hello(1, 2, 'hello', name='骆昊', age=38)


#命名关键参数
#*之前参数名可写可不写,*之后参数名必须写
def foo(a, b, c,*, name, age):
print(a + b + c)
print(name ,':', age)

foo(1, 2, 3, name='Hao', age=38)
foo(a=1, b=2, c=3, name='hao', age=38)
#foo(1, 2, 3, 'HAO', 38) 错误写法


def say_hello(**kwargs):
if 'name' in kwargs:
print('你好,%s!'% kwargs['name'])
elif 'age' in kwargs:
age = kwargs['age']
if age <= 16:
print('你是一个小屁孩')
else:
print('你是一个成年人')
else:
print('请提供个人信息')

say_hello(name='骆昊', age=38)
param = {'name':'王大锤', 'age':16, 'tel':1234556}
#say_hello(param) 不能直接将字典传进去
#如果希望将一个字典作为关键字参数传入,需要在参数前加**
say_hello(**param)


def my_sum(*arg):
pass
mylist = [1, 23, 3]
#如果希望将一个列表或元组作为可变参数传入,需要在参数前加*
my_sum(*mylist)#传入列表时,在参数前加一个*


decorator - 装饰器/包装器

#高阶函数 - f(g(x))

def my_sum(my_list):
total = 0
for val in my_list:
total += val
return total

def my_mul(my_list):
total = 1
for val in my_list:
total *= val
return total
#可以看出这两个函数有很多重复代码,应该可以更优化

my_list = [1, 3, 5, 7, 9]
print(my_sum(my_list))
print(my_mul(my_list))


编程理念

高内聚,低耦合

high cohesion low coupling

高内聚 一个好的函数应该只做好一件事

低耦合 不要让代码跟特定的运行环境耦合在一起

四人帮设计模式

#通过向函数中传入函数 可以写出更通用的代码
#calc函数中的第二个参数是另一个函数,它代表了一个二元运算
#这样calc函数就不需要跟某一种特定的二元运算耦合在一起
#所以calc函数变得通用性更强,可以由传入的第二个参数决定到底做什么

def calc(my_list, op):
total = my_list[0]
for index in range(1, len(my_list)):
total = op(total, my_list[index])
return total

def add(x, y):
return x + y

def mul(x, y):
return x * y

my_list = [1, 3, 5, 7, 9]
print(calc(my_list, add))
print(calc(my_list, mul))


def bar():
def foo(a, b, c,*, name, age):
print(a + b + c)
print(name ,':', age)
return foo

#foo()不能直接访问foo()函数了
x = bar()


装饰器/包装器

def record(fn):#fn是被装饰的函数
def wrapper(*args, **kwargs):
print('准备执行%s函数'% fn.__name__)
print(args)
print(kwargs)
#此行代码在执行被装饰的函数
#在这行代码的前后我们可以附加其他的代码
#这些代码可以让我们在执行函数时做一些额外的工作
val = fn(*args, **kwargs)
print('%s函数执行完成'% fn.__name__)
print('返回了%d'%val)
#返回被装饰的函数的执行结果
return val
return wrapper
#通过装饰器修饰f函数 让f函数在执行过程中可以做更多额外的操作
@record #装饰器语法
def f(n):
if n == 0 or n == 1:
return 1
return n * f(n - 1)

print(f(5))


def record(fn):
def wrapper(*args , **kwargs):
print('hello,world')
val = fn(*args, **kwargs)
return val
return wrapper

@record
def foo(x, y):
return x + y

print(foo(1, 3))


hello,world
4


重点 在类中,里面的方法想要调用已经写好的方法,用self.方法名来实现

class Ultraman(object):

__shots__ = ('_name', '_hp', '_mp')#限定了这个类只能绑定这三个属性

def __init__(self, name, hp=500, mp=100):
self._name = name
self._hp = hp
self._mp = mp

@property  # 属性包装器,可以在下面直接通过对象.name 来访问self._name
def name(self):
return self._name
#属性访问器
@property #如果没有对此对象使用包装器,下面不能使用修改器
def hp(self):
return self._hp
#属性修改器
@hp.setter  # 修改器,可以在下面通过对象.hp来进行访问和修改
def hp(self, hp):
self._hp = hp if hp >= 0 else 0

#属性删除器
@hp.deleter
def hp(self):
del self._hp

ul = Ultraman('AA')
print(ul.name)
#ul.app = True 如果在类里没有限定的话,这个在下面加属性的行为是被允许的


AA


raise ValueError('输入的值无效') #引发值错误


---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-9-69992949a9b6> in <module>()
----> 1 raise ValueError('输入的值无效') #引发值错误

ValueError: 输入的值无效


import math
class Point(object):
"""点"""
def __init__(self, x=0, y=0):
"""
构造器
:param x: 点的橫坐标
:param y: 点的纵坐标
"""
self._x = x
self._y = y

@property
def x(self):
return  self._x

@property
def y(self):
return  self._y

def move_to(self, x, y):
self._x = x
self._y = y

def move_by(self, dx, dy):
self._x += dx
self._y += dy

def distance_to(self, other):
dx = self._x - other.x
dy = self._y - other.y
return math.sqrt(dx ** 2 + dy ** 2)

class Line(object):

def __init__(self, start, end):
self._start = start
self._end = end

@property
def length(self):
return self._start.distance_to(self._end)

# 线 段上有两个点 - has - a - 关联
# 人使用了房子 -use-a - 依赖
# 学生是人 -is-a - 继承
def main():
p1 = Point(3, 5)
p2 = Point()
l1 =Line(p1,p2)
print(l1.length)

if __name__ == '__main__':
main()


继承

#继承-从已经有的类创建新类的过程
#提供继承信息的称为父类(超类/基类)
#得到继承信息的称为子类(派生类/衍生类)
#通过继承我们将子类中的重复代码抽取到父类中
#子类通过继承并复用这些代码来减少重复代码的编写
#将来如果要维护子类的公共代码只需要在父类中进行操作即可
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age

@property
def name(self):
return self._name

@property
def age(self):
return self._age

@age.setter
def age(self, age):
self._age = age

class Student(Person):

b364
def __init__(self, name, age, grade):
super().__init__(name, age) #通过这个方法可以实现将父类的参数引用过来
self._grade = grade

def study(self, course):
print('%s正在学习%s'% (self.name, course))

def watch_av(self):
if self.age >= 18:
print('%s,正在观看岛国爱情动作片'% self.name)
else:
print('%s, 我们推荐你观看熊出没'% self.name)

def watch_av(self):
print('%s正在看片' % (self._name))

class Teacher(Person):

def __init__(self, name, age, title):
super().__init__(name, age)
self._title = title

@property
def title(self):
return  self._title

@title.setter
def title(self, title):
self._title = title

def teach(self, course):
print('%s%s正在教%s' % (self._name, self._title, course))

def main():
pass

if __name__ == '__main__':
main()


"""
思考题
工资结算系统
给员工信息计算出工资
部门经理 15000月薪
程序员 150元/小时
销售员 1200 + 销售额5%的提成

"""


class staff(object):

def __init__(self, name, salary):
self._name = name
self._salary = salary

class DepartmentManager(staff):

def __init__(self, name, salary=15000):
super().__init__(name, salary)

@property
def d_salary(self):
return '%s的工资是%s' % (self._name, str(self._salary))

class Programmer(staff):

def __init__(self, name, salary, man_hours):
super().__init__(name, salary)
self._man_hours = man_hours

@property
def p_salary(self):
return '%s的工资是%s' % (self._name, str(self._man_hours * self._salary))

class Salesman(staff):

def __init__(self, name, salary, sale):
super().__init__(name, salary)
self._sale = sale

@property
def s_salary(self):
return '%s的工资是%s' % (self._name, str(self._salary + self._sale * 0.05))

def main():
d1 = DepartmentManager('唐', 15000 )
g1 = Programmer('王', 150, 240)
s1 = Salesman('李', 1200, 200000 )
print(d1.d_salary)
print(g1.p_salary)
print(s1.s_salary)

if __name__ == '__main__':
main()


唐的工资是15000
王的工资是36000
李的工资是11200.0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: