Python的第三周学习总结

Day 11

2018.3.12

主要内容一:函数的参数

1. 定义可变参数

定义一个函数时需要确定传入的参数,当我们不知道传入的参数的个数时,可以将参数定义为一个元组或者列表传入函数。但是这样做往往较为复杂,python中提供了定义可变参数的方法。
①. 定义可变参数,在参数名前加一个*号即可
②. 如果传入的是一个元组或者列表,在列表和元组前加上*号就行

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

def main():
    mylist = [1, 2, 3, 4, 5]
    # 如果希望将一个列表或元组作为可变参数传入 需要在参数名前加一个*
    print(my_sum(*mylist))

if __name__ == '__main__':
    main()

2. 定义关键字参数

定义关键字参数需在参数名前加上两个**,其他大体上与定义可变参数一致。需要注意的是传入的参数会在函数内部组装成一个字典。

def say_hello(**kwargs):
    for key in kwargs:
        print(key, '----->', kwargs[key])

def main():
    say_hello(name='李云龙', age=38)
    param = {'name': '王大锤', 'age': '16', 'tel': '13455667788'}
    # 如果希望将一个字典作为关键字参数传入 需要在参数前加两个**
    say_hello(**param)

if __name__ == '__main__':
    main()

3. 命名关键字参数

当我们要限制传入与的关键字参数时,就可以使用命名关键字参数。命名关键字参数加上一个分隔符*号即可,*号后面的参数就被视为命名关键字参数。
①. 如果函数定义了一个可变参数,可变参数后面的参数将视为命名关键字参数,可以不用加分隔符*
②. 命名关键字参数必须传入参数名
③. 命名关键字参数有默认值时,可不传入该参数

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

def main():
    foo(1, 2, 3, name='zeng', age='23')

    # *号后面的必须给关键字参数
    # foo(1, 2, 3, 'sun', age='222')

if __name__ == '__main__':
    main()

4. 参数组合

Python中定义参数可以组合使用,但是定义顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
所以,对于任意函数,都可以通过类似func(*args, **kw)的形式调用它,无论它的参数是如何定义的。

主要内容二:高阶函数

1. 函数中可传入一个函数

  • 通过向函数中传入函数 可以写出更通用的代码
  • 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()

2. 装饰器

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
def f(n):
    if n == 0 or n == 1:
        return 1
    return n * f(n - 1)


if __name__ == '__main__':
    print(f(5))

主要内容三:继承

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

    def watch_av(self):
        if self._age >= 18:
            print('%s正在看片.' % self._name)
        else:
            print('%s只能看《熊出没》.' % self._name)


class Student(Person):

    def __init__(self, name, age, grade):
        super().__init__(name, age)
        self._grade = grade

    # # 属性访问器
    # @property
    # def age(self):
    #     return self._age
    #
    # # 属性修改器
    # @age.setter
    # def age(self, age):
    #     self._age = age if 15 <= age <= 25 else 20
    #
    # # 属性删除器
    # @age.deleter
    # def age(self):
    #     del self._age

    @property
    def grade(self):
        return self._grade

    @grade.setter
    def grade(self, grade):
        self._grade = grade

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

    # def watch_av(self):
    #     if self._age >= 18:
    #         print('%s%s正在看片' % self._name)
    #     else:
    #         print('%s只能看《熊出没》' % self._name)


class Teacher(Person):

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

    # @property
    # def name(self):
    #     return self._name
    #
    # @property
    # def age(self):
    #     return self._age
    #
    # @age.setter
    # def age(self, age):
    #     self._age = age

    @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 watch_av(self):
    #     print('%s%s正在观看岛国爱情动作片' % (self._name, self._title))


def main():
    stu = Student('王大锤', 15, '初三')
    stu.study('数学')
    stu.watch_av()
    t = Teacher('骆昊', 38, '叫兽')
    t.teach('Python程序设计')
    t.watch_av()


if __name__ == '__main__':
    main()

课后练习:

写一个银行存取款,转账系统。
class Account(object):

    def __init__(self, *, card_no, owner, balance=0):
        self._card_no = card_no
        self._owner = owner
        self._balance = balance

    @property
    def balance(self):         # 余额
        return self._balance

    def deposit(self, money):   # 存款
        if money > 0:
            self._balance += money
            return True
        return False

    def withdraw(self, money):  # 取款
        if 0 < money <= self._balance:
            self._balance -= money
            return True
        return False

    def transfer(self, other, money):  # 转帐
        if self.withdraw(money):
            other.deposit(money)
            return True
        return False


def main():
    account = Account(card_no='11223344', owner='王大锤')
    print(account.balance)
    account.deposit(2000)
    account.withdraw(500)
    print(account.balance)
    if account.withdraw(5000):
        print(account.balance)
    else:
        print('余额不足')
    account2 = Account(card_no='22334455', owner='李大嘴', balance=120)
    if account.transfer(account2, 800):
        print(account.balance)
        print(account2.balance)
    else:
        print('转账失败')


if __name__ == '__main__':
    main()

Day 12

2018.3.13

主要内容一: 抽象类

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


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

    def __init__(self, name):
        """
        初始化方法

        :param name: 姓名
        """
        self._name = name

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

    @abstractmethod
    def get_salary(self):
        """
        获得月薪

        :return: 月薪
        """
        pass


class Manager(Employee):
    """部门经理"""

    def get_salary(self):
        return 15000.0


class Programmer(Employee):
    """程序员"""

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

    @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, sales=0):
        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:
        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本月工资为: ¥%s元' %
              (emp.name, emp.get_salary()))


if __name__ == '__main__':
    main()

主要内容二:类之间的关系

简单的说,类和类之间的关系有三种:is-a、has-a和use-a关系。

  • is-a关系也叫继承或泛化,比如学生和人的关系、手机和电子产品的关系都属于继承关系。
  • has-a关系通常称之为关联,比如部门和员工的关系,汽车和引擎的关系都属于关联关系;关联关系如果是整体和部分的关联,那么我们称之为聚合关系;如果整体进一步负责了部分的生命周期(整体和部分是不可分割的,同时同在也同时消亡),那么这种就是最强的关联关系,我们称之为合成关系。
  • use-a关系通常称之为依赖,比如司机有一个驾驶的行为(方法),其中(的参数)使用到了汽车,那么司机和汽车的关系就是依赖关系。

课后练习

练习一:描写数学上的分数,加减乘除运算

import math


class Fractions(object):

    def __init__(self, num, den):
        self._num = num
        self._den = den
        self.simplify()
        self.normal()

    @property
    def num(self):
        return self._num

    @property
    def den(self):
        return self._den

    def simplify(self):
        if self._num != 0 and self._den != 1:
            factor = math.gcd(abs(self._num), abs(self._den))
            if factor > 1:
                self._num //= factor
                self._den //= factor
        return self

    def normal(self):
        if self._den < 0:
            self._den = -self.den
            self._num = -self._num
        return self

    def __str__(self):
        if self._num == 0:
            return '0'
        elif self._den == 1:
            return str(self._num)
        else:
            return '%d/%d' % (self._num, self._den)

    def add(self, other):
        return Fractions((self._num * other.den + self._den * other.num), (self._den * other.den))

    def __add__(self, other):
        return self.add(other)

    def sub(self, other):
        return Fractions((self._num * other.den - self._den * other.num), (self._den * other.den))

    def __sub__(self, other):
        return self.sub(other)

    def mul(self, other):
        return Fractions(self._num * other.num, self._den * other.den)

    def __mul__(self, other):
        return self.mul(other)

    def div(self, other):
        return Fractions(self._num * other.den, self._den * other.num)

    def __truediv__(self, other):
        return self.div(other)


def main():
    f1 = Fractions(1, 2)
    print(f1)
    f2 = Fractions(1, -3)
    print(f2)
    print(f1 + f2)
    print(f1 - f2)
    print(f1 * f2)
    print(f1 / f2)


if __name__ == '__main__':
    main()

Day 13 Day 14

2018.3.14~2018.3.15

主要内容

第十三天和第十四天的学习内容是:主要通过pygame模块来编写了五子棋,大球吃小球,贪吃蛇等小游戏。会不会编写游戏目前来说不是主要的,重点是让我们进一步的认识到面向对象编程的重要性,有了面向对象的编程思想处理起复杂的问题来才会显得井井有条,代码看上去也比较通俗易懂,不会很乱。

from abc import ABCMeta, abstractmethod
from random import randint

import pygame

BLACK_COLOR = (0, 0, 0)
GREEN_COLOR = (0, 255, 0)
FOOD_COLOR = (230, 185, 185)

UP = 0
RIGHT = 1
DOWN = 2
LEFT = 3


class GameObject(object, metaclass=ABCMeta):

    def __init__(self, x=0, y=0, color=BLACK_COLOR):
        self._x = x
        self._y = y
        self._color = color

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

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

    @abstractmethod
    def draw(self, screen):
        pass


class Wall(GameObject):

    def __init__(self, x, y, width, height, color=BLACK_COLOR):
        super().__init__(x, y, color)
        self._width = width
        self._height = height

    @property
    def width(self):
        return self._width

    @property
    def height(self):
        return self._height

    def draw(self, screen):
        pygame.draw.rect(screen, self._color,
                         (self._x, self._y, self._width, self._height), 4)


class Food(GameObject):

    def __init__(self, x, y, size, color=FOOD_COLOR):
        super().__init__(x, y, color)
        self._size = size
        self._hidden = False

    def draw(self, screen):
        if not self._hidden:
            pygame.draw.circle(screen, self._color,
                               (self._x + self._size // 2, self._y + self._size // 2),
                               self._size // 2, 0)
        self._hidden = not self._hidden


class SnakeNode(GameObject):

    def __init__(self, x, y, size, color=GREEN_COLOR):
        super().__init__(x, y, color)
        self._size = size

    @property
    def size(self):
        return self._size

    def draw(self, screen):
        pygame.draw.rect(screen, self._color,
                         (self._x, self._y, self._size, self._size), 0)
        pygame.draw.rect(screen, BLACK_COLOR,
                         (self._x, self._y, self._size, self._size), 1)


class Snake(GameObject):

    def __init__(self):
        super().__init__()
        self._dir = LEFT
        self._nodes = []
        self._alive = True
        for index in range(5):
            node = SnakeNode(290 + index * 20, 290, 20)
            self._nodes.append(node)

    @property
    def dir(self):
        return self._dir

    @property
    def alive(self):
        return self._alive

    @property
    def head(self):
        return self._nodes[0]

    def change_dir(self, new_dir):
        if (self._dir + new_dir) % 2 != 0:
            self._dir = new_dir

    def move(self):
        if self._alive:
            snake_dir = self._dir
            x, y, size = self.head.x, self.head.y, self.head.size
            if snake_dir == UP:
                y -= size
            elif snake_dir == RIGHT:
                x += size
            elif snake_dir == DOWN:
                y += size
            else:
                x -= size
            new_head = SnakeNode(x, y, size)
            self._nodes.insert(0, new_head)
            self._nodes.pop()

    def collide(self, wall):
        """
        撞墙

        :param wall: 围墙
        """
        head = self.head
        if head.x < wall.x or head.x + head.size > wall.x + wall.width \
                or head.y < wall.y or head.y + head.size > wall.y + wall.height:
            self._alive = False

    def eat_food(self, food):
        if self.head.x == food.x and self.head.y == food.y:
            tail = self._nodes[-1]
            self._nodes.append(tail)
            return True
        return False

    def eat_me(self):
        pass

    def draw(self, screen):
        for node in self._nodes:
            node.draw(screen)

    def show_score(self, screen):
        my_font = pygame.font.SysFont('宋体', 40)
        score = my_font.render('score: ', False, [255, 0, 0])
        screen.blit(score, (460, 30))
        if len(self._nodes) - 5 > 0:
            new_score = str((len(self._nodes) - 5) * 10)
            sco = my_font.render(new_score, False, [255, 0, 0])
            screen.blit(sco, (550, 30))

    def show_top_score(self, screen):
        other_font = pygame.font.SysFont('楷体', 30)
        top_score = other_font.render('top score: ', False, [255, 0, 0])
        screen.blit(top_score, (460, 50))
        tops = []

        top = (len(self._nodes) - 5) * 10
        tops.append(top)
        tops.sort(reverse=True)
        his = tops[0]
        best = other_font.render(str(his), False, [255, 0, 0])
        screen.blit(best, (570, 50))

def main():

    def refresh():
        """刷新游戏窗口"""
        screen.fill((242, 242, 242))
        wall.draw(screen)
        food.draw(screen)
        snake.draw(screen)
        snake.show_score(screen)
        snake.show_top_score(screen)
        pygame.display.flip()

    def handle_key_event(key_event):
        """处理按键事件"""
        key = key_event.key
        if key == pygame.K_F2:
            reset_game()
        else:
            if snake.alive:
                new_dir = snake.dir
                if key == pygame.K_w:
                    new_dir = UP
                elif key == pygame.K_d:
                    new_dir = RIGHT
                elif key == pygame.K_s:
                    new_dir = DOWN
                elif key == pygame.K_a:
                    new_dir = LEFT
                if new_dir != snake.dir:
                    snake.change_dir(new_dir)

    def create_food():
        row = randint(0, 29)
        col = randint(0, 29)
        return Food(10 + 20 * col, 10 + 20 * row, 20)

    def reset_game():
        nonlocal food, snake
        food = create_food()
        snake = Snake()

    wall = Wall(10, 10, 600, 600)
    food = create_food()
    snake = Snake()
    pygame.init()
    screen = pygame.display.set_mode((620, 620))
    pygame.display.set_caption('贪吃蛇')
    screen.fill((242, 242, 242))
    pygame.display.flip()
    clock = pygame.time.Clock()
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.KEYDOWN:
                handle_key_event(event)
        if snake.alive:
            refresh()
        clock.tick(10)
        if snake.alive:
            snake.move()
            snake.collide(wall)
            if snake.eat_food(food):
                food = create_food()

    pygame.quit()


if __name__ == '__main__':
    main()

Day 15

2018.3.16

学习内容一:文件读写

读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。

import time


# 异常机制 - 处理程序在运行过程中出现的意外状况的手段
# 因为不是所有的问题都能够在写程序调试程序的时候就能发现

# 打开文件 --> 判断大小 --> 分配内存 --> 读取文件 --> 关闭文件


def main():
    try:
        # 一个点当前路径,两个点上一级路径
        with open('../hello.txt', 'r', encoding='utf-8') as fs:
            # 第一种方式:全部读取
            # content = fs.read()
            # print(content)
            #
            # 第二种方式:一行一行的读取
            # for line in fs:
            #     print(line, end='')
            #     time.sleep(0.5)
            # print(content)
            #
            #第三种方式: 读取成列表
            mylist = fs.readlines()
            print(mylist)
    except FileNotFoundError as e:
        print(e)
        print('指定的文件无法打开。')
    except IOError:
        print('读写文件时出现错误')

    print('程序执行结束。')


if __name__ == '__main__':
    main()

学习内容二:错误处理

from math import sqrt


def is_prime(n):
    assert n > 0
    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 FileNotFoundError:
        # except可以写多个分别用于处理不同的异常状况
        pass
    except IOError:
        # 如果try中出现了状况就通过except来捕获错误(异常)进行对应的处理
        print('读写文件时出现错误')
    else:
        # 如果没有出状况那么可以吧无风险的代码放到else中执行
        pass
    finally:
        print('释放文件资源')
        # 不管程序正常还是异常最后这里的代码一定会执行
        # 所以此处最适合做释放外部资源的操作
        for fs in fs_list:
            fs.close()
    print('操作完成!')


if __name__ == '__main__':
    main()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值