ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

学习Python第三周总结

2021-08-07 12:04:04  阅读:206  来源: 互联网

标签:总结 __ return 函数 Python self 第三周 print def


学习Python第三周总结

一、函数和模块

1.1 函数的定义

​ Python中的函数的自变量称为函数的参数,而因变量称为函数的返回值

在Python中可以使用def关键字来定义函数,命名规则跟变量的命名规则是一致的。在函数名后面的圆括号中可以放置传递给函数的参数,就是我们刚才说到的函数的自变量,而函数执行完成后我们会通过return关键字来返回函数的执行结果,就是我们刚才说的函数的因变量。一个函数要执行的代码块(要做的事情)也是通过缩进的方式来表示的,跟之前分支和循环结构的代码块是一样的。

1.2函数的参数

如果函数中没有return语句,那么函数默认返回代表空值的None。另外,在定义函数时,函数也可以没有自变量,但是函数名后面的圆括号是必须有的。

  • 位置参数——在没有特殊处理的情况下,函数的参数都是位置参数

  • 关键字参数——我们在设计函数时,如果既不知道调用者会传入的参数个数,也不知道调用者会不会指定参数名,那么同时使用可变参数和关键字参数。关键字参数会将传入的带参数名的参数组装成一个字典,参数名就是字典中键值对的键,而参数值就是字典中键值对的值

重点提醒:关键字参数一定要在位置参数的后面。

代码例子如下:

# *args--->可变参数--->可以接收零个或任意多个位置参数--->将位置参数打包成元组
# **kwargs--->可以接收零个或任意多个关键字参数--->将所有的关键字参数打包成一个字典


def add(*args, **kwargs):
    print(args, type(args))
    # print(kwargs, type(kwargs))
    total = 0
    for arg in args:
        if type(arg) in (int, float):
            total += arg
    for value in kwargs.values():
        if type(value) in (int, float):
            total += value
    return total


print(add(1, 2, 4, a=3))


def mul(*args, **kwargs):
    # print(args, type(args))
    # print(kwargs, type(kwargs))
    total = 1
    for arg in args:
        if type(arg) in (int, float):
            total *= arg
    for value in kwargs.values():
        if type(value) in (int, float):
            total *= value
    return total


print(mul(1, 2, 4, a=3))

函数的例题一:

玩家摇两颗骰子,如果第一次摇出了7点或11点,玩家胜;如果摇出了2点、3点、12点,庄家胜;
如果摇出了其他的点数,游戏继续,玩家重新摇色子;如果玩家摇出了第一次摇的点数,玩家胜;
如果玩家摇出了7点,庄家胜;如果玩家摇出其他点数,游戏继续,玩家重新摇色子,直到分出胜负。

游戏开始之前,玩家有1000元的初始资金,玩家可以下注,赢了获得下注的金额,输了就扣除下注的金额,
游戏结束的条件是玩家把钱输光。
import random


def roll_dice(num):
    """
    摇骰子

    :param num: 骰子的数量
    :return: 摇出的点数
    """
    total = 0
    for _ in range(num):
        total += random.randrange(1, 7)
    return total


def win():
    global x
    print('玩家胜')
    x += z


def lose():
    global x
    print('庄家胜')
    x -= z


x = 1000
while x > 0:
    print(f'玩家总资产为{x}元')
    z = 0
    while z <= 0 or z > x:
        z = int(input('请下注'))
        m = roll_dice(3)
    print(f'玩家摇出了{m}点')
    if m in (7, 11):
        win()
    elif m in (2, 3, 12):
        lose()
    else:
        while True:
            n = roll_dice(3)
            print(f'玩家摇出了{n}点')
            if n == m:
                win()
                break
            elif n == 7:
                lose()
                break
print('玩家已破产,游戏结束')

例题二:

# 求阶乘
def fac(num):
    """求阶乘"""
    result = 1
    for i in range(2, num + 1):
        result *= i
    return result


m = int(input('m = '))
n = int(input('n = '))
print(fac(m) // fac(n) // fac(m - n))

1.3标准库中的模块和函数

Python标准库中提供了大量的模块和函数来简化我们的开发工作,random模块可以提供生成随机数和进行随机抽样的函数;而time模块则可以提供和时间操作相关的函数。在Python标准库中的math模块中还包括了计算正弦、余弦、指数、对数等一系列的数学函数。随着我们进一步的学习Python编程知识,我们还会用到更多的模块和函数。

Python标准库中还有一类函数是不需要import就能够直接使用的,我们将其称之为内置函数,这些内置函数都是很有用也是最常用的,下面的表格列出了一部分的内置函数。

函数说明
abs返回一个数的绝对值,例如:abs(-1.3)会返回1.3
bin把一个整数转换成以'0b'开头的二进制字符串,例如:bin(123)会返回'0b1111011'
chr将Unicode编码转换成对应的字符,例如:chr(8364)会返回'€'
hex将一个整数转换成以'0x'开头的十六进制字符串,例如:hex(123)会返回'0x7b'
input从输入中读取一行,返回读到的字符串。
len获取字符串、列表等的长度。
max返回多个参数或一个可迭代对象(后面会讲)中的最大值,例如:max(12, 95, 37)会返回95
min返回多个参数或一个可迭代对象(后面会讲)中的最小值,例如:min(12, 95, 37)会返回12
oct把一个整数转换成以'0o'开头的八进制字符串,例如:oct(123)会返回'0o173'
open打开一个文件并返回文件对象(后面会讲)。
ord将字符转换成对应的Unicode编码,例如:ord('€')会返回8364
pow求幂运算,例如:pow(2, 3)会返回8pow(2, 0.5)会返回1.4142135623730951
print打印输出。
range构造一个范围序列,例如:range(100)会产生099的整数序列。
round按照指定的精度对数值进行四舍五入,例如:round(1.23456, 4)会返回1.2346
sum对一个序列中的项从左到右进行求和运算,例如:sum(range(1, 101))会返回5050
type返回对象的类型,例如:type(10)会返回int;而type('hello')会返回str

二、高阶函数

​ Python中的函数是一等函数,但是函数本身也可以作为函数的参数或返回值,而且还可以赋值给变量。这就是所谓的高阶函数。通常使用高阶函数可以实现对原有函数的解藕合操作。

Lambda函数——没有名字而且一句话就能写完的函数,唯一的表达式就是函数的返回值。也被称为匿名函数

例如:

# fn ---> 一个实现二元运算的函数(可以做任意的二元运算)
def calc(*args, op, init_value=0, **kwargs):
    total = init_value
    for arg in args:
        if type(arg) in (int, float):
            total = op(total, arg)
    for value in kwargs.values():
        if type(value) in (int, float):
            total = op(total, value)
    return total


# def add(x, y):
#     return x + y
#
#
# def mul(x, y):
#     return x * y


# print(calc(11, 22, 33, 44, op=add))
print(calc(11, 22, 33, 44, op=lambda x, y: x + y))
# print(calc(11, 22, 33, 44, op=mul, init_value=1))
print(calc(11, 22, 33, 44, init_value=1, op=lambda x, y: x * y))
fn = lambda x, y: x - y
print(calc(11, 22, 33, 44, init_value=100, op=fn))

三、递归调用

​ 函数如果直接或者间接的调用了自身,那么这种调用就被称为递归调用。

递归函数的两个要点:

  • 递归公式(第n次跟第n-1次的关系)
  • 收敛条件(什么时候停止递归调用)
# 不管函数是调用别的函数,还是调用自身,一定要做到快速收敛。
# 在比较有限的调用次数内能够结束,而不是无限制的调用函数。
# 如果一个函数(通常指递归调用的函数)不能够快速收敛,那么就很有可能产生下面的错误
# RecursionError: maximum recursion depth exceeded
# 最终导致程序的崩溃。


def fac(num: int) -> int:
    """求阶乘(递归写法)"""
    if num == 0:
        return 1
    return num * fac(num - 1)


if __name__ == '__main__':
    # return 5 * fac(4)
    # return 4 * fac(3)
    # return 3 * fac(2)
    # return 2 * fac(1)
    # return 1 * fac(0)
    # return 1
    print(fac(5))



def fib(n):
    if n in (1, 2):
        return 1
    return fib(n - 1) + fib(n - 2)


if __name__ == '__main__':
    for i in range(1, 21):
        print(i, fib(i))

例题一:编写实现对列表元素进行冒泡排序的函数

def bubble_sort(items, ascending=True, gt=lambda x, y: x > y):
    """
    冒泡排序
    :param items: 待排序的列表
    :param ascending:
    :param gt:
    :return:
    """
    items = items[:]
    for i in range(1, len(items)):
        swapped = False
        for j in range(0, len(items) - i):
            if gt(items[j], items[j + 1]):
                items[j], items[j + 1] = items[j + 1], items[j]
                swapped = True
        if not swapped:
            break
    if not ascending:
        items = items[::-1]
    return items


if __name__ == '__main__':
    nums = [35, 96, 12, 7, 20, 8, 15]
    print(bubble_sort(nums, ascending=False))
    print(nums)

例题二:编写实现查找列表元素的函数:

def seq_search(items: list, key) -> int:
    """
    顺序查找
    :param items: 待查找的元素
    :param key: 要找的元素
    :return: 找到了返回元素的索引,找不到返回-1
    """
    for index, item in enumerate(items):
        if item == key:
            return index
    return -1


def bin_search(items: list, key) -> int:
    """
    二分查找
    :param items:待查找的元素(元素有序)
    :param key: 要找的元素
    :return: 找到了返回元素的索引,找不到返回-1
    """
    start, end = 0, len(items) - 1
    while start <= end:
        mid = (start + end) // 2
        if key > items[mid]:
            start = mid + 1
        elif key < items[mid]:
            end = mid - 1
        else:
            return mid
    return -1


if __name__ == '__main__':
    nums1 = [5, 4, 7, 20, 8, 15]
    print(seq_search(nums1, 20))
    print('_' * 20)
    nums2 = [4, 5, 7, 8, 15, 20]
    print(bin_search(nums2, 15))
    print(bin_search(nums2, 45))

四、面向对象编程

1、定义

面向对象编程是一种编程范式(程序设计的方法论)。

如果要用一句话来概括面向对象编程,我认为下面的说法是相当精准的。

面向对象编程:把一组数据和处理数据的方法组成对象,把行为相同的对象归纳为,通过封装隐藏对象的内部细节,通过继承实现类的特化和泛化,通过多态实现基于对象类型的动态分派。

对象:对象是可以接收消息的实体,面向对象编程就行通过给对象发消息达到解决问题的目标。对象 = 数据 + 函数(方法),即对象将数据和操作数据的函数从逻辑上变成了一个整体。

对象有以下四个特征:

  • 一切皆为对象
  • 对象都有属性和行为
  • 每个对象都是独一无二的
  • 对象一定属于某个类

:将有共同特征(静态特征和动态特征)的对象的共同特征抽取出来之后得到的一个抽象概念。简单的说,类是对象的蓝图(模板),有了类才能够创建出这种类型的对象。

2、创建和使用对象

1、定义类:类的命名使用驼峰命名法(每个单词首字母大写)

​ 数据抽象:找到和对象相关的静态特征(属性)

​ 行为抽象:找到和对象相关的动态特征(方法)

2、创建对象

3、给对象发消息

例如:

# 第一步:定义类
class Student:
    """学生"""

    # 数据抽象(属性)
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # 行为抽象(方法)
    def eat(self, name):
        """吃饭"""
        print(f'{self.name}正在吃{name}')

    def study(self, course_name):
        """
        学习
        :param course_name: 课程名字
        """
        print(f'{self.name}正在学习{course_name}')

    def play(self, game_name):
        """
        玩耍
        :param game_name: 游戏名字
        """
        print(f'{self.name}正在玩{game_name}')
        
# 第二步:创建对象--->构造器语法--->类名(..., ...)
Stu1 = Student('黄小宇', 18)
Stu2 = Student('周大大', 21)

# Student.study(stu1, 'Python程序设计')
# 第三步:给对象发消息(调用对象的方法)
Stu1.eat('螺蛳粉')

Stu2.study('Python程序设计')

3、魔术方法

魔术方法(魔法方法)—> 有特殊用途和意义的方法
init —> 初始化方法,在调用构造器语法创建对象的时候会被自动调用
str —> 获得对象的字符串表示,在调用print函数输出对象时会被自动调用
repr —> 获得对象的字符串表示,把对象放到容器中调用print输出时会自动调用
—> representation
lt —> 在使用 < 运算符比较两个对象大小时会自动调用

如果一个变量的取值只有有限个选项,可以考虑使用枚举类型。
Python中没有定义枚举类型的语法,但是可以通过继承Enum类来实现枚举类型。
结论1:枚举类型是定义符号常量的最佳选择!!!
结论2:符号常量(有意义的名字)总是优于字面常量!!

4、继承和多态

继承:对已有的类进行扩展创建出新的类,这个过程就叫继承。
提供继承信息的类叫做父类(超类、基类),得到继承信息的类称为子类(派生类)。

继承是实现代码复用的一种手段,但是千万不要滥用继承。

继承是一种is-a关系。
a student is a person.
a teacher is a person.
a programmer is a person.

子类直接从父类继承公共的属性和行为,再添加自己特有的属性和行为,
所以子类一定是比父类更强大的,任何时候都可以用子类对象去替代父类对象。

Python中的继承允许多重继承,一个类可以有一个或多个父类。
如果不是必须使用多重继承的场景下,请尽量使用单一继承。

5、两个类之间有哪些关系

~ is-a关系:继承—>从一个类派生出另一个类
a student is a person
~ has-a关系:关联—>把一个类的对象作为另外一个类的对象的属性
a person has an identity card
——(普通)关联

​ —— 强关联:整体和部分的关联,聚合和合成
use-a关系:依赖—>一个类的对象作为另外一个类的方法的参数或返回值
​ a person use a vehicle(交通工具)

6、面向对象编程的四大支柱

1、抽象(abstraction):提取共性(定义类就是一个抽象过程,需要做数据抽象和行为抽象)
2、封装(encapsulation):把数据和操作数据的函数从逻辑上组成一个整体(对象)
—>隐藏实现细节,暴露简单的调用接口
3、继承(inheritance):扩展已有的类创建新类,实现对已有类的代码复用
4、多态(polymorphism):给不同的对象发出同样的消息,不同的对象执行了不同的行为。
—>方法重写(override):子类对父类已有的方法,重新给出自己的实现版本

​ 在重写方法的过程中,不同的子类可以对父类的同一个方法给出不同的实现版本,
那么该方法在运行时就会表现出多态性

7 经典例题

例题一:

现在有三类员工:
部门经理:固定月薪,15000
程序员:计时结算月薪,
销售员:底薪 + 提成,底薪1800,销售额 %5提成
写一个面向对象的编程实现工资的计算
from abc import abstractmethod


class Employee:
    def __init__(self, name):
        self.name = name

    @abstractmethod
    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

    def get_salary(self):
        return 200 * self.working_hour


class Salesman(Employee):

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

    def get_salary(self):
        return 1800 + 0.05 * self.sales


def main():
    emps = [Manager('刘备'), Programmer('诸葛亮'), Salesman('关羽')]

    for emp in emps:
        if type(emp) == Programmer:
            emp.working_hour = int(input(f'请输入{emp.name}本月工作时长'))
        elif type(emp) == Salesman:
            emp.sales = int(input(f'请输入{emp.name}本月销售额'))
        print(f'{emp.name}本月工资:{emp.get_salary()}元')


if __name__ == '__main__':
    main()

例题二:

# 创建一个时钟对象(可以显示时/分/秒),让它运转起来
import time


class Clock:

    # 数据抽象
    def __init__(self, hour=0, minute=0, second=0):
        self.hour = hour
        self.min = minute
        self.sec = second

    def show(self):
        """显示时间"""
        return f'{self.hour:0>2d}:{self.min:0>2d}:{self.sec:0>2d}'

    # 行为抽象
    def run(self):
        """走字"""
        self.sec += 1
        if self.sec == 60:
            self.sec = 0
            self.min += 1
            if self.min == 60:
                self.min = 0
                self.hour += 1
                if self.hour == 24:
                    self.hour = 0


if __name__ == '__main__':
    clock = Clock()
    while True:
        print(clock.show())
        time.sleep(1)
        clock.run()

五、总结

​ Python中的函数可以使用可变参数*args和关键字参数**kwargs来接收任意数量的参数,而且传入参数时可以带上参数名也可以没有参数名,可变参数会被处理成一个元组,而关键字参数会被处理成一个字典。Python中的函数也是对象,所以函数可以作为函数的参数和返回值,也就是说,在Python中我们可以使用高阶函数。如果我们要定义的函数非常简单,只有一行代码且不需要名字,可以将函数写成Lambda函数(匿名函数)的形式。

​ 面向对象编程是一种非常流行的编程范式,除此之外还有指令式编程函数式编程等编程范式。由于现实世界是由对象构成的,而对象是可以接收消息的实体,所以面向对象编程更符合人类正常的思维习惯。类是抽象的,对象是具体的,有了类就能创建对象,有了对象就可以接收消息,这就是面向对象编程的基础。定义类的过程是一个抽象的过程,找到对象公共的属性属于数据抽象,找到对象公共的方法属于行为抽象。

​ 这周的函数和面向对象编程是重点,也是难点。需要反复的去巩固练习,需要用时间去练习,以此来让我们能够熟练的掌握。

标签:总结,__,return,函数,Python,self,第三周,print,def
来源: https://blog.csdn.net/m0_60333585/article/details/119483446

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有