一、编程语言比较
1.静态:C语言/C++
变量的数据类型,在创建变量时就被定义,之后给变量赋值时,需要符合变量的数据类型
动态:Python语言
对变量数据类型没有限制,变量数据类型可以动态变化
3.编译型:C/C++
解释型:Python
二、基本语法
1.注释:
功能:
1.解释代码
2.屏蔽现有代码
(1) 单行注释
# 井号开头的一行,表示注释内容,运行过程中不会执行,起到解释说明的作用
(2) 多行注释
######################################################
# 通过多个单行注释
# 编写多行注释
# 很多公司采用的一种手段,这种方式可以让注释非常整洁
######################################################
代码
'''
多行注释,通常是对重要的代码进行详细
描述的注释文本
print():标注输出,控制台输出一段信息
"hello":输出的第一个文本数据
"world":输出的第二个文本数据
sep=",":输出的多个文本数据之间的分隔符
'''
print("hello", "world", sep=",")
(3) 文档注释
文档注释:对整个python文件进行说明的文本注释
"""
三对双引号包含的一段说明文本、
@File : d02_stu_mgt.py.py(什么名称的文件)
@Date : 2024/4/13 15:53 (python文件的创建时间)
@Author : 牟文斌(Muwenbin) (文件的作者)
@Contact : 大牧老师 damu@aliyun.com (联系方式)
@License : (C) Copyright 2023, Example Corp. (授权)
@Desc : 这是一个标准注释示例 (说明备注)
"""
2.输入输出
程序运行过程中,不可避免的需要屏幕上展示信息(标准输出)、也需要通过键盘获取用户的输入信息(标准输入),Python中提供了两个功能方法,专门用于输出和输入的操作:
print()
:标准输出
input()
:标准输入
3. 变量的命名
变量是程序中使用最多的一个语法,存储了程序中的核心:数据
对于变量的命名非常重要,Python对于变量命名包含如下的规则:
-
语法规则:变量名称必须由字母、数字、下划线组成,数字不能开头
-
语义规则:变量名称由一个或者多个英文单词组成,不同单词使用下划线分隔
-
语义规则:见名知意,看到变量名称,知道变量的作用
命名方法:
1.大驼峰命名法:将每一个单词的首字母大写,常用于给 类 命名
2.小驼峰命名法:将除第一个单词以外的所有单词的首字母大写,在其他编程语言中常用于 变量和函数的命名
3.下划线命名法:所有单词小写,单词中间用下划线分割
4.运算符
字符串比较:
两字符串比较,从第一个字符开始比较asc码,如果第一个就比较出,则就是两个字符串的比较结果,如果第一个字符相等,则递推。
123>121,输出结果为:true
逻辑运算符: not and or
身份运算符 is:
判断两个变量是否指向了同一个对象
结果:
成员运算符 in:
位运算符:
三目运算符:
结果:200 (真输出左边,假输出右边)
三、图形化设计
1.在cmd命令框中调用Python
C:\Users\29107>python
Python 3.11.6 (tags/v3.11.6:8b6ee5b, Oct 2 2023, 14:57:12) [MSC v.1935 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> a=10
>>> b=20
>>> a+b
30
###运行测试
2.调用图形化界面并进行操作
>>> import turtle as t #调用图形化模块turtle,并将其改名为 t
>>> t.showturtle() #调用可视化界面
>>> libpng warning: iCCP: known incorrect sRGB profile
libpng warning: iCCP: known incorrect sRGB profile
libpng warning: iCCP: known incorrect sRGB profile
libpng warning: iCCP: known incorrect sRGB profile
libpng warning: iCCP: known incorrect sRGB profile
libpng warning: iCCP: known incorrect sRGB profile
libpng warning: iCCP: known incorrect sRGB profile
libpng warning: iCCP: known incorrect sRGB profile
libpng warning: iCCP: known incorrect sRGB profile
libpng warning: iCCP: known incorrect sRGB profile
>>>
>>> t.forward(100) #使箭头移动100个像素
>>> t.left(90) #使箭头向左旋转90度
>>> t.forward(100)
>>> t.color("#ff0000") #箭头和线颜色变为红色
>>> t.forward(100)
>>> t.forward(100)
>>> t.color("#00ff00") #变为绿色
>>> t.left(150)
>>> t.forward(250)
一个像素是一个整数,一个整数是32位
turtle中用不到透明度,所以格式为:ff0000
结果:
四、选择结构
选择结构是根据条件是否满足,去选择性的执行一段代码的处理流程。
选择结构分为:
-
单分支结构:根据条件是否满足,判断是否执行某一段代码
-
双分支结构:根据条件是否满足,判断是否代码段A或者代码段B;注意代码A和代码B不会同时执行
-
多分支结构:可以设置多个判断条件,去区分多个不同的执行步骤
1.单分支结构:
if 条件 :
执行代码
2.双分支结构:
if 条件 :
执行代码
else :
执行代码
3.多分支结构:
if 条件 :
执行代码
else 条件 :
执行代码
else :
执行代码
五、循环结构:
循环结构(loop),表示根据条件是否满足,重复执行一段代码的过程。
-
while循环结构:自定义条件的循环结构
-
for循环结构/for..in循环结构:主要用于序列数据的遍历
基本语法
while 条件:
条件为True时,重复执行的代码块(多行代码)
举例:
for 临时变量 in 序列数据:
# 序列数据:多个数据的集合,如字符串就是多个字符的集合
循环内部就可以通过临时变量依次操作序列数据
举例:
关键字
break关键字:代码一旦执行,直接跳出循环,相当于终止循环
例子中一旦判断出一个数是否为质数,则终止循环得到结果。
continue关键字:中断本次循环,直接开始下一次循环
例子中,当选出预留票后,循环需要继续执行,当卖出全部的火车票,循环结束。
六、容器
1.列表-list
列表可以存储多个元素,并且类型不受限制,定义一个列表我们可以使用中括号,元素之间使用逗号隔开,并且可以随时扩充不受限制。
列表增添:
末尾添加数据使用append(数据)函数。
中间插入数据使用inset(序号,数据)函数。
使用extend(数组)扩展数组。
列表删除:
remove(数据):根据元素的值删除元素。
pop(序号):根据列表序号删除元素,不填序号默认删除末尾元素。
clear():清空列表所有内容。
列表查询:
index(序号):查找该序号元素,如果该序号元素不存在则抛出异常(报错)。
count(元素):统计该元素在列表中出现次数。
print(ls[序号]):若序号是负数则是从右到左。
列表排序:
sort(列表):按照列表中int类型的数据的ascll码进行排序(只能适用于int型)。
ls.reverse():逆序输出。
列表的复制:
copy():为浅拷贝,保存的是复制列表的地址,被复制的列表数据变化,拷贝的列表数据也会变化。
copy.deepcopy():为深拷贝,从头到尾不会因为被复制的列表的变化而变化。
尽量使用浅拷贝,如果修改了数据对副本有影响(影响后续运算),使用深拷贝。
2.元组--tuple
元组是一种不可变的序列类型。
3.集合--set
可存储多个数据,并且可以存储多种类型,数据是无序的并且不允许数据重复,只支持for循环,使用{}创建,帮助去重复,求并集,交集,差集。
并集函数union()
交集函数intersection()
差集函数defference()
add():添加新元素,无法判断元素出现的位置
update():更新集合,合并集合
discard():阐述元素,如果不存在也不会报错
列表,集合,元组可以分别通过list(),set(),tuple(),转换成相应的容器类型。
4.字典-dict
声明字典:
字典相关操作函数:
函数 | 描述 |
---|---|
clear() | 清空字典数据-了解 |
copy() | 复制字典数据-了解 |
fromkeys() | 通过指定的key创建字典-了解 |
get()[掌握] | 根据key获取数据 |
items()[掌握] | 获取所有的键值对数据 |
keys()[掌握] | 获取所有的key数据 |
pop()[掌握] | 根据key删除一个键值对数据 |
popitem() | 随机删除一个数据 |
setdefault() | 添加数据,如果key存在什么都不做 |
update() | 更新数据 |
values()[掌握] | 获取所有的value数据 |
字典遍历:
通过key遍历:
通过value遍历:
以元祖形式遍历(也可省略括号 for key,value in dc.items() ):
七、函数
最基础的加法函数:
注意:函数内return为返回值,切记不要使用print()
1.函数参数
参数类型:默认值参数,位置参数,可变参数,关键值参数,命名参数。
默认值参数:在形参列中提前赋值,若觉得不好用,可主动传参改变数值。
默认值参数可以当做一个全局的变量,每调用一次就会修改原有的内容,下一次调用在修改后的结果上继续。
所以,虽然默认参值参数不限制参数类型为可变,但建议设置为不可变参数。
位置参数:按默认顺序给参数赋值,若不按顺序必须特殊声明。
可变参数:将实际参数包装在元组中交给函数运算,在函数中可变参数就是一个元组
若图中*args后还有位置参数a,b,此时a,b为命名参数,必须指名道姓传参
命名参数:必须指名道姓的参数,一般出现在可变参数后或者*args或者*后。
关键字参数:参数名称可以在传递参数时临时赋予
参数组合传递(不建议):
参数顺序:
# 参数顺序
# 位置参数 -> 可变参数 -> 默认值参数 -> 关键字参数
def fn(name, *args, age=19, **kwargs):
print("位置参数:", name)
print("可变参数:", *args)
print("默认值参数:", age)
print("关键字参数:", kwargs)
# fn("tom")
# fn("jerry", "java", gender="男")
fn("jerry", "java", 29, age=30, gender="男")
2.局部变量、全局变量
局部变量:函数内部声明的变量称为局部变量,包括函数的形式参数也是局部变量
特点:局部变量只能被当前作用域/作用范围访问,只能被当前函数内访问,出了当前函数其他任何位置访问不到该数据
def fn(name):
# name 局部变量
# max 局部变量
max = 10
print(name, max)
fn("tom")
def fn():
# 局部变量
x = 10
# 函数内可以访问
print("x:", x) # 10
fn()
# 函数外不能访问
print(x) # NameError: Name 'x' is not defined
全局变量:在一个Python文件中,声明在所有函数外部的变量
# 全局变量
max_words = 1200
def fn():
pass
fn()
print(max_words) # 1200
特点:
-
全局变量存储当前Python文件中的所有代码都可以共享的数据
-
全局变量可以被多个函数直接访问
-
global 全局变量名称
函数中修改操作全局变量数据
全局变量的访问和修改:
# 全局变量的访问和修改
max_age = 100
def fn():
# 声明访问全局变量
global max_age
# 如果没有global,声明了一个和全局变量同名的局部变量)
max_age = 120
# 访问全局变量
print("max_age 内:", max_age)
fn()
print("max_age 外:", max_age)
name = "z3"
def function():
# 如果要在函数中"修改"全局变量,需要使用global对全局变量进行声明
a = 1
b = 1
print(a + b)
print(name)
function()
print(name)
3.全局变量与局部变量的选择
# name = "张三"
#
#
# # 内聚性:内聚性越高表示代码对外界依赖越低,耦合性越低,
# # 内聚性的代码一定程度上会消耗更多的系统资源
# # 所以使用高内聚还是高耦合的代码取决于,你开发的系统他的追求是高性能,易于开发
# def function():
# age = 100
# print(name)
# print(age)
#
#
# function()
# # 全局变量可以在程序的任意位置使用
# # 也因为全局变量作用域太大,如果某个脚本,错误的修改了该全局变量,可能会导致程序的问题。
# print(name)
# # 局部变量只能在函数中使用,出了函数无法使用
# # 当我们要使用的数据,就在函数范围内有意义,我们应该使用局部变量。
# # 局部变量可以提升代码的内聚性
4.值传递与引用传递
值传递:传参数的时候,实参将自己 副本 传递到函数中参与运算
引用传递:传参数的时候,实参将自己传递到函数中参与运算
# 值传递:所有的不可变数据类型都是值传递(number(int,float),str,bool,tuple)
num = 100
def add(a):
a += 100
print(f"a={a}")
add(num)
print(f"num={num}")
# 引用传递 : 所有的可变类型数据都是引用传递
ls = [100]
def add(a):
a[0] += 100
print(a)
add(ls)
print(ls)
5.匿名函数
# 函数作为参数
def add(a, b):
return a + b
def minus(a, b):
return a - b
def main(function, a, b): # minus , 10 , 20
return function(a, b) # minus(10,20)
result = main(add, 10, 20)
print(result)
result = main(minus, 10, 20)
print(result)
运行结果:
30
-10
# lambda函数
# 语法结构:lambda:参数1,参数2....参数n:一行代码
# 整个lambda函数只能有一行代码
# 自动返回代码的运行结果
# lambda函数一般会直接作为实参传递其他函数
result = main(lambda a, b: a + b, 10, 20)
print(result)
result = main(lambda a, b: a - b, 10, 20)
print(result)
运行结果:
30
-10
# map函数:
# 他会将传入的序列中的每一个元素 通过一个lambda函数进行修改
ls = [1, 2, 3, 4, 5, 6]
result = list(map(lambda n: n ** 2, ls))
print(result)
运行结果:
[1, 4, 9, 16, 25, 36]
# filter函数:
# 他会根据lambda函数过滤条件对序列进行筛选
ls = [1, 2, 3, 4, 5, 6]
result = list(filter(lambda n: n % 2 == 0, ls))
print(result)
运行结果:
[2, 4, 6]
# sort函数:
# 根据lambda函数进行排序
ls = [1, 2, 3, 4, '10', '20']
result = list(sorted(ls, key=lambda n: int(n)))
print(result)
运行结果:
[1, 2, 3, 4, '10', '20']
6. 函数返回值
# python的返回值可以返回单个值,也可以返回多个值
# 本质上返回多个值,是返回一个元组
def circle_area(r, pi=3.14):
return pi * r * r
def get_volume(height, r):
area = circle_area(r)
volume = area * height
return volume
v = get_volume(10, 10)
print(v)
运行结果:
3140.0
# 通过注解指定函数参数的数据类型
def add(a: int, b: int) -> int:
return a + b
result = add("123", "345")
print(result)
运行结果:
123345
八、面向对象编程
面向过程: 通过完成一步一步的步骤从而解决问题的编程思路
面向对象: 视角不再是解决某问题,而是包含了多个问题的系统,这个系统我们称之为对象
函数和变量:在类视角中,就是方法和属性
1.基本框架
class Student:
# 类属性 :所有的实例共享的一个属性
count = 0
# 魔法方法:构造函数,当通过类名创建实例时会触发执行的函数
def __init__(self, grade, pro, name):
# self.变量名,实例属性:每一个实例都有一套自己的属性
# 构造函数只负责初始化类的实例属性
self.grade = grade
self.pro = pro
self.name = name
Student.count += 1
# 实例方法 是每一个实例都拥有的方法,实例方法中可以随意的操作实例属性
def show_info(self):
print(self.grade, self.pro, self.name)
# 类方法:所有实例共享的一个方法,类方法中可以随意操作类属性
@classmethod
def show_count(cls):
print(f"人类的数是:{cls.count}")
# 静态方法:静态方法可以跟类毫无关联,如果开发者想要将该方法写到类中,可以将其声明为静态方法
@staticmethod
def add(a, b):
return a + b
# 当判断两个实例是否相等时触发的__eq__函数,判断结果就是__eq__的返回值
def __eq__(self, other):
if self.name == other.name:
return True
else:
return False
# 当两个实例之间相加时,触发__add__函数,相加的结果就是__add__的返回值
def __add__(self, other):
return Student(self.name + other.name, self.grade + other.grade, self.pro + other.pro)
# 当实例被str()转为字符串时,触发__str__函数,转化的结果就是__str__的返回值
def __str__(self):
s = f"名字:{self.name} 年级{self.grade} 专业:{self.pro}"
return s
s1 = Student(1, "计科", "张三")
s2 = Student(2, "软工", "李四")
s3 = Student(3, "电信", "王五")
s1.show_info()
s2.show_info()
s3.show_info()
Student.show_count()
2.面向对象三大基本特征之一:封装
封装的好处:
1.提升代码可读性,只暴露一些关键的方法和属性,供人使用,使用者无需关心的方法和属性全部隐藏起来
2.提升代码的安全性3.我们可以通过给被隐藏的属性设置set和get方法来限制调用者的操作
class Human:
def __init__(self, name, age, height):
self.name = name
# 私有属性:变量名前面有__就是私有属性,在类的外部无法调用,并且无法被继承
self.__age = age
# 受保护的属性:变量名前面有一个_就是受保护的属性,在类外部不建议嗲用,可以被继承
self._height = height
# 封装的方法1:在各个编程语言中我们都可以给私有或受保护的属性通过get和set设置方法
# def get_age(self):
# return self.__age
#
# def set_age(self, age):
# if type(age) == int:
# self.__age = age
# else:
# print("参数必须是整数")
# 封装的方法2:使用Property类来创建一个私有或受保护属性的外部代言人
# 当给age进行赋值时,会自动调用set_age方法。当获取age的数值,会返回get_age的结果。
# age = property(get_age,set_age)
# 封装方法3:使用装饰器@property @xxx.setter
@property
def age(self):
return self.__age
@age.setter
def age(self, age):
if type(age) == int:
self.__age = age
else:
print("参数必须是整数")
h = Human("小张", 60, 183)
h.age = "1000"
print(h.age)
# 创建一个类,要有一个私有属性,该私有属性具备get和set方法。
3.面向对象三大基本特征之二:继承
继承可以帮助我们高效的重复利用已经写好的代码,让我无需写重复的代码。
继承的作用:
1.修改父类的方法
2.扩展父类的方法
3.重复利用已有的方法# class 类名(要继承的类):
# 。。。。。# 被继承的类可以称作:超类,父类,基类
# class Human:
# def __init__(self, name, age):
# self.name = name
# self.__age = age
#
# def get_age(self):
# return self.__age
#
#
# class Student(Human):
# # 子类的构造函数必须调用父类的构造函数
# # 私有属性:可以被继承到,但是我们无法直接使用,只能通过父类定义的公有方法来进行操作
# def __init__(self, name, age):
# super().__init__(name, age)
#
# def show_info(self):
# print(self.name)
#
# s1 = Student("张三",20)
# s1.show_info()
# print(s1.get_age())
class MyStr(str):
def __sub__(self, other):
if self.isdigit() and other.isdigit():
return str(int(self) - int(other))
def __add__(self, other):
if self.isdigit() and other.isdigit():
return str(int(self) + int(other))
else:
return super().__add__(other)
s1 = MyStr("123")
s2 = MyStr("23a")
s3 = s1 + s2
print(s3)
# 继承一下int类
# 修改 + 法运算 让整型相加的结果是拼接
4.面向对象三大基本特性之三:多态
class Animal:
def speak(self):
pass
class Dog(Animal):
# 函数的重写:当实例调用的函数在父类和子类中都存在,优先调用自己的
def speak(self):
# 函数重写,可以在内部调用父类的同名函数
super().speak()
print("汪")
class Cat(Animal):
def speak(self):
super().speak()
print("喵")
class Tiger:
def speak(self):
print("wow")
def animal_speak(animal: Animal) -> None:
animal.speak()
d = Dog()
animal_speak(d)
c = Cat()
animal_speak(c)
t = Tiger()
animal_speak(t)
# 函数的重载:同名不同参函数。
# python中不存在函数重载,但是在面向对象中可以通过@Property装饰间接的实现函数的重载
# 详见封装的第三种方式
def add(a, b):
return a + b
def add(a, b, c):
return a + b + c
print(add(10, 20, 30))