简明关键字参数/可变参数、对象的3种关系及文件的读写

关键字参数、可变参数

decorator - 装饰器/包装器

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

# 可变参数
def my_sum(*args):
    total = 0
    for val in args:
        total += val
    return total

# 命名关键字参数
# 后面调用函数时*号后面的需要传入关键字才会生效
def foo(a, b, c, *, name, age):
    print(a + b + c)
    print(name,':', age)

def main():
    say_hello(name='念阳枭', age='23', qq='654321', gender=True)
    param = {'name':'刘闯','age':24,'tel':'12345678'}
    # 如果希望将一个字典作为关键字参数传入,需要在参数前放两个*
    say_hello(**param)
    foo(1, 2, c=3, name='念', age=25)

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

# 高阶函数
# 通过向函数中传入函数,可以写出更通用的代码
# 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

def main():
    mylist = [1,2,3,4,5]
    print(calc(mylist, add))
    print(calc(mylist, mul))

if __name__ == '__main__':
    main()

(属性的)包装器/装饰器decorator

# 装饰器语法
def record(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  # record记录,履历
def f(n):
    if n == 0 or n == 1:
        return 1
    return n * f(n-1)

if __name__ == '__main__':
    # fw = record(f)
    # print(fw(5))
    print(f(5))

类和类/对象和对象之间的三大关系

线段上有两个点 - has-a - 关联关系 整体不可分割的,叫做强关联/聚合 eg:人有手,车有引擎

人使用了房子 - use-a - 使用,依赖关系

学生是人 - is-a - 继承关系

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

class Person(object):

    def __init__(self,name,age):
        self._name = name 
        self._age = age

    @property  # getter - 属性访问器
    def name(self):
        return self._name

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

    @age.setter  # setter - 属性修改器
    def age(self,age):
        self._age = age

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

class Student(Person):

    def __init__(self, name, age):
        super().__init__(name,age)  # 从父类Person继承属性name,age
        self._course = course

    @property
    def course(self):
        return self._course

    @course.setter
    def study(self,course):
        return '%s正在学习%s' % (self._name, course)

    # 方法重写(override) - 覆盖/置换/重写  
    # 子类在继承父类方法之后,对方法进行了重新实现
    # 当我们给子类对象发送watch_av消息时执行的是子类重写过的方法
    def watch_av(self):
        print('学生正在跟苍老师学习技术')

def main():
    stu1 = Student('李牧',40)
    stu2 = Student('钟岳',17)
    stu1.study('HTML网页设计')
    stu2.watch_av()

if __name__ == '__main__':
    main()
  • Python没有从语言层面支持抽象类的概念,我们可以通过abc模块来制造抽象类的效果

    在定义类的时候通过指定metaclass=ABCMeta可以将类声明为抽象类

    抽象类是不能创建对象的,抽象类存在的意义是专门给其他类继承

    abc模块中还有一个包装器abstractmethod,通过这个包装器可以将方法包装为抽象方法,必须要求子类进行重写

from abc import ABCMeta,abstramethod

class Employee(object,metaclass=ABCMeta):
    '''员工'''

    def __init__(self,name):
        '''初始化方法'''
        self._name = name

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

    @abstractemethod
    def get_salary(self):
        '''获得月薪...'''
        pass

class Manager(Employee):

    def get_salary(self):
        return 15000.00

class Programmer(Employee):

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

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

    @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.0 * self._working_hour

class Salesman(Employee):

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

    @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.0 + self._sales * 0.05

def main():
    emps = [
        Manager('猴子'), Programmer('罗刹'),
        Manager('龙女'), Salesman('狐狸'),
        Salesman('牛魔'), Programmer('神将'),
        Programmer('和尚')
    ]
    for emp in emps:
        # isinstance判定一个对象是不是指定的类型
        if isinstance(emp, Programmer):
            emp.working_hour = int(input('请输入%s本月工作时间:' % emp.name))
        elif isinstance(emp,Salesman):
            emp.sales = float(input('请输入%s本月销售额:' % emp.name))
        # 同样是接收get_salary这个消息,但是不同的员工表现出了不同的行为
        # 因为三个子类都重写了get_salary方法,所以这个方法会表现出多态行为
        print('%s本月工资为: ¥%.2f元' % (emp.name,emp.get_salary()))


if __name__ == '__main__':
    main()

读取文件、写文件

import time

def main():
    fs = open('hello.txt', 'r', encoding='utf-8')  # 把‘r’换成‘w’就是写文件
    # 表示打开当前路径下文件‘hello.txt’
    # content = fs.read()
    # print(content)

    # for line in fs:  # 一次读一行
    #    print(line, end = '')
    #    time.sleep(0.5)
    mylist = fs.readlines()
    print(mylist)
    fs.close()

    # 写文件
    # fs.write('弹木吉他抒情一些\n')
    # fs.write('可回忆骚动一整夜\n')
    # fs.write('寒冷却下不了雪\n')

    # 用with读取文件,如果在with下出现错误导致程序崩溃,就会退出,不会影响其他位置的程序
    # 输入文件路径也可以,.表示当前路径,..表示上一级路径
    with open('./abc/hello.txt', 'r', encoding='utf-8') as fs: 
        mylist = fs.readlines
        for line in mylist:
            print(line, end='')
            time.sleep(1)


if __name__ == '__main__':
    main()
  • 异常机制 - 处理程序在运行过程中出现的意外状况的手段

    因为不是所有的问题都能够在写程序调试程序的时候就能发现

import time

def main():
    try:  # 把要读取的文件放到try里面保护起来,让文件即使读取出现错误也能够继续执行后面的代码
        with open('./abc/hello.txt', 'r', encoding='utf-8') as fs: 
            mylist = fs.readlines()
            for line in mylist:
                print(line, end='')
                time.sleep(1)
    except FileNotFoundError:  # 捕获文件异常
        print('指定的文件无法打开.')  
    # except IOError:
    #     pring('读写文件时出现错误.')

    # except FileNotFoundError as e:
    #    print(e)             打印出现错误的文件
    #    print('指定的文件无法打开')
    print('程序执行结束.')


if __name__ == '__main__':
    main()
# 把1-100,101-1000,1001-10000的素数分别放入三个文件夹
from math import sqrt

def is_prime(n):
    assert n > 0  # 检查n是否是有效数,无效则程序报异常不执行
    for factor in range(2, int(sqrt(n)) + 1):
        if n % factor == 0:
            return False
    return True if n != 1 else False

def main():
    filenames = ('a.txt', 'b.txt', 'c.txt')
    fs_list = []
    try:  # 我们也可以把可能出状况(在执行时有风险)的代码放到try代码块来执行
        for filename in filenames:
            fs_list.append(open(filename, 'w', encoding='utf-8'))
        for number in range(1, 10000):
            if is_prime(number):
                if number < 100:
                    fs_list[0].write(str(number) + '\n')
                elif number < 1000:
                    fs_list[1].write(str(number) + '\n')
                else:
                    fs_list[2].write(str(number) + '\n')

    except IOError:  # 如果try中出现了状况就通过except来捕获错误(异常)进行对应的处理
        print('读写文件发生错误')
    except FileNotFoundError:  # except可以写多个分别用于处理不同的异常状况
        pass
    # except BaseException:  处理所有的异常状况
    #     pass

    # else:  如果没有出状况,那么可以把无风险的代码放到else中执行
    #     for number in range(1, 10000):
    #         if is_prime(number):
    #             if number < 100:
    #                fs_list[0].write(str(number) + '\n')
    #            elif number < 1000:
    #                 fs_list[1].write(str(number) + '\n')
    #             else:
    #                 fs_list[2].write(str(number) + '\n')
    finally:
        # 释放文件资源,不管程序正常还是异常,最后这里的代码一定会执行,保证资源释放
        # 所以此处是最好的释放外部资源的位置,因为这里的代码总是会执行
        for fs in fs_list:
            fs.close
    print('操作完成!')


if __name__ == '__main__':
    main()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章