Python编程语言总结与答疑

  • 要求: 看完本章节所有课程内容,并完成作业,优先回答和作业相关的问题
  • 有什么问题在评论区回复

本章演示代码

Sign in · GitLab

学习Python思路

基础路线

参考资料

  • 官方文档

https://docs.python.org/zh-cn/3/tutorial/index.html

进阶学习

  • Python cookbook(难度较大,有基础后阅读)

Python Cookbook 3rd Edition Documentation — python3-cookbook 3.0.0 文档

常见问题汇总

  1. 直接上传代码,不要传压缩包
  2. 不要再venv中写代码

书写问题

  • 缩进问题
  • 环境配置问题(包管理)
    • 不要上传venv在自己的仓库里面,可以在.gitignore中添加忽略
    • 如果需要环境管理,使用下面的命令
生成环境配置文件
 pip3 freeze > requirements.txt

如何Debug定位问题

Debug 的方式


作业

题目

  1. 创建两个类,分别叫做Timo 和Jinx。 每个类都包含有hp、power 这两个类变量
  2. 分别在两个类都创建一个 fight 方法,fight 方法的参数为 题目要求的参数

作业思路解析

@startuml
Class HeroFactory{
    Class create_hero()
}

class Hero{
    #int hp
    #int power

    ~ fight()

}
class Jinx{
    #int hp
    #int power

    ~ fight()
    ~String speak_lines()

}
class EZ{
    #int hp
    #int power

    ~ fight()
    ~String speak_lines()

}
HeroFactory--> EZ: 实例化
HeroFactory--> Jinx: 实例化
Hero<|-- EZ : 继承
Hero<|-- Jinx: 继承
@enduml


优秀作业

刘志华

liuzhihua: 霍格沃兹测试学院作业提交 - Gitee.com

  • 虽然只是拓展了简单的for 循环,但是还是值得鼓励,而且代码写的很整洁

曾初开

https://gitee.com/zengchukai/test-study/blob/master/two_week_homework/hero.py

  • 点评: 虽然语法知识都是课程内的,但是尝试将录播学到的知识内容融入作业中。是非常好的学习习惯

卢树涛

https://gitee.com/lushutao2/myhomework/tree/master/python%20homework

  • 点评: 敢于拓展,想法很多,基础扎实,对于python语法知识比较熟悉
  • 建议:注释可以多写一些,给其他同学多多参考一下

杨宇帆

https://gitee.com/sailyang00/ceshiren/tree/master/class2/moudle1/pythonProject

  • 点评:对 python 的语法基础还是很不错的,而且编程很有想法,没有为了完成作业而完成作业,加了很多自己了解的python语法知识进去,还使用了配置文件管理数据
  • 建议: 文件管理有点乱和项目无关的文件比如 venv 可以放在.gitignore中,__call__在这个场景下可以使用类装饰器实现, __new__的参数建议设定成不定长参数,因为构造函数一旦多传参数进去,就会报错

classmethod、 staticmethod

from random import randint


class Hero:
    # 比如 类变量已经定义好了,因为
    # 可能有其他同事正在使用这个类
    #
    hero_hp = 0
    hero_power = 0
    hero_name = ""
    def fight(self, enemy_hp, enemy_power, enemy_name):
        """
        :param enemy_hp: 敌人的血量,是整型
        :param enemy_power: 敌人的血量,是整型
        :return:
        """
        # 在定义死循环,一定要有终止条件,以及跳出循环的步骤比如break。
        while True:
            # 计算英雄最终的血量, 通过self.类变量 去调用 类中的类变量
            self.hero_hp = self.hero_hp - randint(1, enemy_power)
            # 计算敌人的最终血量
            enemy_hp = enemy_hp - self.hero_power
            print(f"{self.hero_name}的血量为{self.hero_hp}, {enemy_name}的血量为{enemy_hp}")
            # 判断谁的血量先到0
            if self.hero_hp<=0:
                print(f"{enemy_name}赢了")
                break
            elif enemy_hp<=0:
                print(f"{self.hero_name}赢了")
                break

    @classmethod
    def name_add_number(cls, nickname):
        cls.hero_name = cls.hero_name + nickname
        print(cls.hero_name)

    def name_add_number_instance(self):
        self.hero_name = self.hero_name+ "3号"


class Jinx(Hero):
    hero_hp = 1200
    hero_power = 210
    hero_name = "Jinx"
    # def __init__(self):

class EZ(Hero):
    hero_hp = 1100
    hero_power = 190
    hero_name = "EZ"

class Timo(Hero):
    hero_hp = 1100
    hero_power = 190
    hero_name = "timo"

if __name__ == '__main__':
    # 多行注释快捷键 alt + /
    EZ.name_add_number("2号")

    ez = EZ()
    # ez.name_add_number_instance()
    ez2 = EZ()
    print(ez.hero_name)
    print(ez2.hero_name)

    # jinx.fight(ez.hero_hp, ez.hero_power)
    # ez.fight(jinx.hero_hp, jinx.hero_power, "Jinx")

    #

from python_practice.hero import EZ, Jinx, Timo

# static 使用场景

class HeroFactory:
    # staticmethod 使用场景,
    # 方法所有涉及到的逻辑都没有使用实例方法或者实例变量的时候
    @staticmethod
    def create_hero(hero):
        # 快捷导入 alt/option + 回车
        # 当传入的参数为ez 的时候,返回
        # EZ 的实例对象
        if hero == "ez":
            return EZ()
        elif hero == "jinx":
            return Jinx()
        elif hero == "timo":
            # 鼠标左键 加 ctrl/command 可以进行代码的跳转
            return Timo()
        # 当传入的参数都不符合上面的条件时,报出异常
        else:
            raise Exception("此英雄不在英雄工厂当中")

# 判断语句, __name__ 变量, "__main__"字符串
if __name__ == '__main__':
    print("这是main")
    #节省实例化的过程
    jinx = HeroFactory.create_hero("jinx")
    ez = HeroFactory.create_hero("ez")
    jinx.fight(ez.hero_hp, ez.hero_power, ez.hero_name)

课后调查表

https://jinshuju.net/f/s6VovW

讲作业的时候拓展下,用上循环,把攻击值变为随机,血量小于零时游戏在结束,自己试了试没成功 :grinning:

1、多线程用实践例子再讲解下
2、在pycharm中使用git提交代码时,设置控制版本路径提示“
The directory already exists and it is not empty 目录已经存在并且不是空的”怎么解决


老师
python的所有可变数据结构设计原则 : 返回值是None
如何理解这句话 ?

在类函数中,函数圆括号中什么时候需要self,什么时候不需要?

烦请再讲一下,实际工作应用中的环境管理。
举例:python各种版本,第三方库的各种版本,怎么查找使用呢?怎么维护管理呢?

平时怎么积累第三方库的使用呢?举例:有时候不知道是不是存在对应的第三方库或内置模块,怎么学习呢?

python语言和C语言的区别,方向:C语言是编译链接。 python是个什么原理呢?
实际使用中,python不需要编译的特性有什么好处呢?

在编程中,怎么理解数据结构。方向:代码易读性,代码复杂度,应怎样培养这种意识呢?

老师 问一下关于线程的问题,这里讲到了可以继承threading.Thread,实现重写自己的线程。
在这里重写了run函数,执行 super继承父类的重构方法后,为什么会自动调用run方法?是Thread 的源码调的run方法吗?
我尝试查看了源码确实会调用run方法,但是调用关系比较乱,没理清,老师会讲一下吗?

...
class MyThread(threading.Thread):

    def __init__(self, func, args, name=''):

        super().__init__()

        self.func = func

        self.args = args

        self.name = name

    def run(self):

        self.func(*self.args)
...

这句摘录于官方文档

https://docs.python.org/zh-cn/3/tutorial/datastructures.html

image

意思是相比其他的语言,python 在对于可变数据结构,这些方法修改的是原本的数据结构,而不是在原本数据之上生成一个新的数据结构,作为返回值返回回来

概念性的知识可以看知乎维基的科普。不建议在这上面太过于纠结。对语言的体感要经过深入学习之后感受才会比较深刻。

https://zh.wikipedia.org/wiki/Python
https://zhuanlan.zhihu.com/p/146906080

这两个是一个问题,其实编程和传统型知识学习区别最大的一部分就是要学会去查资料,以及怎么查资料。

第三方库种类繁多,作用不同,用到了再去查找或者在群里讨论,不要一开始就把这些库背下来。比如,我现在要做平台开发,需要解决后端的跨域问题,我也不知道用哪个库能解决这些问题,那我可能就会搜 “flask如何解决跨域”。

  1. 多写代码,跟着项目练习多做拓展,使用公司的产品做自动化测试。能力的成长是循序渐进的
  2. 多看优秀的开源框架,可以从简单的开始看起,比如httprunner。
  3. 图解算法、 大话设计模式

多线程录播视频已经在重录了,视频重录好之后,会更新视频,并让班班通知大家。多线程的知识比较独立,目前还用不到,在后面的课程用到了之后会给大家介绍具体的实际例子和场景

换个目录获名称即可

课上演示

这个知识点涉及到:classmethod、 staticmethod、以及普通方法

名称 定义 调用 关键字 使用场景
classmethod 至少需要一个cls参数 类名.方法名() 或者实例名.方法名() @classmethod 如果需要对类属性,即静态变量进行限制性操作
staticmethod 无默认参数 类名.方法名() 或者实例名.方法名() @staticmethod 无需类或实例参与
普通方法 至少需要一个参数self 实例名.方法名() 方法内部涉及到实例对象属性的操作

老师,后面框架和平台的搭建会用到哪些工厂模式的应用呢?简单工厂、工厂方法、抽象工厂都有应用吗?可以先介绍一下应用场景吗?

后面会用到PO 设计模式,不会用到工厂模式,设计模式不是本课程主讲内容,如果很有兴趣的话,可以推荐你一本书《大话设计模式》

from random import randint


class Hero:
    hero_hp = 0
    hero_power = 0
    hero_name = ""
    def fight(self, enemy_hp, enemy_power, enemy_name):
        """
        :param enemy_hp: 敌人的血量,是整型
        :param enemy_power: 敌人的血量,是整型
        :return:
        """
        # 在定义死循环,一定要有终止条件,以及跳出循环的步骤比如break。
        while True:
            # 计算英雄最终的血量, 通过self.类变量 去调用 类中的类变量
            self.hero_hp = self.hero_hp - randint(1, enemy_power)
            # 计算敌人的最终血量
            enemy_hp = enemy_hp - self.hero_power
            print(f"{self.hero_name}的血量为{self.hero_hp}, {enemy_name}的血量为{enemy_hp}")
            # 判断谁的血量先到0
            if self.hero_hp<=0:
                print(f"{enemy_name}赢了")
                break
            elif enemy_hp<=0:
                print(f"{self.hero_name}赢了")
                break


class Jinx(Hero):
    hero_hp = 1200
    hero_power = 210
    hero_name = "Jinx"
    # def __init__(self):

class EZ(Hero):
    hero_hp = 1100
    hero_power = 190
    hero_name = "EZ"

class Timo(Hero):
    hero_hp = 1100
    hero_power = 190
    hero_name = "timo"

if __name__ == '__main__':

    jinx = Jinx()
    ez = EZ()
    # jinx.fight(ez.hero_hp, ez.hero_power)
    ez.fight(jinx.hero_hp, jinx.hero_power, "Jinx")