Python——装饰器和继承

#关键字参数**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):

    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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值