面向对象(二)

关于python中的一些法则

程序员都是懒惰的 都是急躁的 因此为了能达到该目标应该知道一些官方的法则
开闭原则 ——软件实现应该对扩展开放,对修改关闭
依赖倒转原则
里氏替换原则 —— 子类可以替换父类
接口隔离原则
合成聚合复用原则 —— 可以强关联的地方就不要继承
迪米特法则(最少知识原则):
高内聚 低偶合
一个函数只干一件事,一个类只做类该做的事 不要特定绑定到一起

比如下面的例子 如果计算两个数的阶乘和求和
如果定义多个函数就违背了迪米特法则
因此我们有两种解决方法:


# decorator -装饰器  f(f(x)) 高阶函数
# calc函数中的第二个参数就是另一个函数 他代表的是一个二元运算
# 这样calc函数就不需要跟某一特定的二院运算偶合在一起
# 所哟calc函数就变得更加通用 可以由传入的第二个参数来决定到底做什么
def calc(m, a): #函数传函数
    total = m[0]
    for index in range(1, len(m)):
        total = a(total,m[index])
    return total
def add(x ,y):
    return x + y
def mul(x, y):
    return x * y
list = [1,2,3,4]
print(calc(list,add))
calc(calc,mul)

lamubda

当然我们为了写更少的函数还可以命名 匿名函数:lamubda

print(calc(lambda x , y : x + y)

命名关键字参数

” * “后面的参数必须给参数名,前面的随便你给不给

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

    foo(1,2,3,'h',15)# 如果没有*这样写是对的
    foo(1,2,c=3,name='h',age=18)#这样写才能判断正确

# 根据参数名来决定如何执行
def hello(**kwargs):#关键字参数 不知道参数多少个并且要用到你的参数名字——传进来的是字典
    print(kwargs)
    if 'name'in kwargs:
        print('你好%s' % kwargs['name'])
    elif 'age' in kwargs:
        age = kwargs['age']
        if age < 18:
            print('未成年')
    else:
        print('提供个人信息')


def main():
    hello(name='A',age=20)#多个参数组装成字典
    param = {'name':'wang', 'age':13}
    hello(**param)
    #如果传入的是一个字典那么就需要在参数前加**
    # 同理在传入元组时候是*

if __name__ == '__main__':
    main()

装饰器

通过命名装饰器我们可以先执行装饰器内的内容, 然后执行装饰器外的内容
先定义一个装饰器 然后再@该装饰器

def record(fn):
    def wrapper(*args, **kwargs):
        print('A')
        # 此行代码在执行被装饰的函数
        # 在这行代码的前后我们可以附加其他代码
        # 这些代码可以让我们去做一些额外的工作
        val = fn(*args, **kwargs)  # 为了把元组或字典拆散
        return val

    return wrapper


# 通过装饰器修饰函数f 让函数f在执行过程可以做更多额外操作
@record
def f(n):
    if n == 0 or n == 1:
        return 1
    return n * f(n - 1)


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


if __name__ == '__main__':
    print(f(5))
    print(e(x=5, y=6))
#这里就会先打印A再执行e函数

在类中固定参数

如果类中你写的参数不想被添加新元素那么可以用”slots

class Ultraman(object):
    # 表示类里只能有这些值
    __slots__ = ('_name', '_hp', '_mp')

继承

在创建类中 class XXX(object) 括号中的位置表示继承,其意义在于创建该类能够拥有括号中类的属性 一般没有可继承的类都用object表示
就好比儿子继承父亲的属性特征,因此也叫父类,子类 在运用继承关系的时候要用到函数

““superr”
用法:super().init(要继承的属性)

同时在python中没有从语言层面支持抽象概念
我们可以通过abc模块来制造抽象效果
在定义类的时候通过指定metaclass=ABCMeta 可以将类声明为抽象类
抽象类是不能创建对象的 抽象类存在的意义是专门拿给其他类继承
abc模块中还有个包装器 abstractmethod
通过包装器可以将方法包装为抽象方法 必须要求子类进行重写

isinstance 判断对象里有什么
isinstance(列表,里面你想要的参数)
在定义类的时候通过指定metaclass=ABCMeta 可以将类声明为抽象类

下面来进行讲述:


from abc import ABCMeta, abstractclassmethod


class Employee(object, metaclass=ABCMeta):

    # 在self后加入._表示受保护的程序 虽然是可以修改因为python设计的就是都可以修改 但这作为提醒不能修改
    # self表示类取值本身
    def __init__(self, name):
        """
    初始化方法
        :param name:姓名
        """
        self._name = name

    @property  # 属性访问器 只能读 不能改写
    def name(self):
        return self._name

    @abstractclassmethod  # 表示子类必须加上这个方法
    def get_salary(self):
        pass


class Manager(Employee):

    def get_salary(self):
        return 15000


class Programmer(Employee):

    def __init__(self, name):
        super().__init__(name)
        self._working_hour = 0

    @property
    def working_hour(self):
        return self._working_hour

    # 非必要属性给setter 表示随时可以修改的值
    @working_hour.setter
    def working_hour(self, working_hour):
        self._working_hour = working_hour if working_hour > 0 else 0

    def get_salary(self):
        return 150 * self._working_hour


class Salersman(Employee):

    def __init__(self, name):
        super().__init__(name)
        self._sales = 0

    @property
    def sales(self):
        return self._sales

    @sales.setter
    def sales(self, sales):
        self._sales = sales if sales > 0 else 0

    def get_salary(self):
        return 1200 + self._sales * 0.05


def main():
    emps = [
        Manager('A'), Programmer('123'), Salersman('大大')
    ]
    for emp in emps:
        # 判断是不是什么对象
        if isinstance(emp, Programmer):
            emp.working_hour = int(input('输入%s工作时间:' % emp.name))
        elif isinstance(emp, Salersman):
            emp.sales = int(input('%s销售额是:' % emp.name))
        # 同样是接受get_salary这个消息 但是不同员工都是不同方法
        # 因为三个字类都重写了get_salary方法 所以这个方法会表现多态行为
        print('%s本月工资:¥%.2f元' %
              (emp.name, emp.get_salary()))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值