Python入门
Python
Python与Java的区别
-
语言类型
-
Python:动态类型语言。变量的类型在运行时确定,不需要显式声明类型。
-
Java:静态类型语言。变量的类型在编译时就确定了,要求显式声明变量类型。
-
-
语法
-
Python:语法简洁,通常不需要分号结尾。使用缩进来定义代码块,这使得代码更具可读性。
-
Java:语法较为复杂,需要用分号结尾,使用大括号
{}
来定义代码块。
-
-
内存管理
-
Python:自动内存管理,使用垃圾回收机制(GC)来处理内存回收。
-
Java:也使用垃圾回收机制,但提供了更多的控制选项,例如选择不同的垃圾回收器。
-
-
面向对象
-
Python:支持多重继承,类和对象的创建相对灵活。所有的东西都是对象,包括数字和函数。
-
Java:不支持多重继承(使用接口来实现类似功能),强制面向对象的编程,基本数据类型不是对象。
-
-
运行环境
-
Python:通常通过解释器执行,可以在不同平台上直接运行(有 CPython、Jython 等实现)。
-
Java:编译成字节码,然后通过 Java 虚拟机(JVM)执行,这使得 Java 程序具有平台无关性(“写一次,处处运行”)。
-
-
性能
-
Python:由于其动态特性和解释执行,通常性能较低,但在很多应用场景下足够使用。可以通过 C 扩展(如 NumPy)提高性能。
-
Java:通常比 Python 快,因为它是编译成字节码并通过 JVM 优化运行的。Java 的性能在许多情况下优于 Python。
-
-
使用场景
-
Python:广泛用于数据科学、机器学习、自动化脚本、Web 开发(如 Django 和 Flask)等。Python 的库和框架非常丰富。
-
Java:广泛用于企业级应用、Android 开发、大型系统开发等。Java 的生态系统支持多种企业级功能和工具。
-
-
多线程
-
Python:由于全局解释器锁(GIL)的存在,Python 的多线程在 CPU 密集型任务中效果不佳。但对于 I/O 密集型任务,多线程仍然有效。
-
Java:支持真正的多线程和并发编程。Java 的多线程实现更为高效,适用于 CPU 密集型和 I/O 密集型任务。
-
-
库和框架
-
Python:有大量第三方库和框架,适合快速开发和原型设计。例如,Django、Flask、Pandas、TensorFlow 等。
-
Java:也有大量的库和框架,但它们通常更注重企业级应用和大规模系统,例如 Spring、Hibernate、Apache Camel 等。
-
-
编程范式
-
Python:支持多种编程范式,包括面向对象编程(OOP)、函数式编程和过程式编程。
-
Java:主要支持面向对象编程(OOP),虽然也可以进行函数式编程(从 Java 8 开始支持 Lambda 表达式)。
第一个Python 程序
print("Hello World!!!")
基础语法
字面量
含义:代码中,被写在代码中固定的值称之为字面量
常见的字面量类型:
- 整数 int
- 浮点数 float
- 字符串 string
666
13.14
"你好"
print(666)
print(13.14)
print("你好")
注释
单行注释:单行注释使用#
作为开头来表示
# 这是单行注释
多行注释:
'''
这是多行注释,
能够注释很多行
'''
变量
含义:在程序运行时,能储存计算结果或能表示值的抽象概念
定义变量的方式为 变量名 = 值
的方式
money = 688
money = money - 10
数据类型
- 整数 int
- 浮点数 float
- 字符串 string
- 布尔类型 bool
Python中可以通过type()
来查看数据类型
print(type("你好"))
print(type(666))
print(type(11.123))
name = "酱香豆腐皮"
string_type = type(name)
print(name_type)
flag = True # False
print(type(flag)) #<class 'bool'>
字符串
字符串定义
字符串定义有三种方式
-
单引号定义法
name = 'nihao'
-
双引号定义法
name = "nihao"
-
三引号定义法
name = '''nihao'''
字符串拼接
Python中可以用+
来拼接字符串
name = '哈哈哈哈'
print("晚上好" + name + "!")
字符串格式化
方式一:通过 %
格式化
name = "xxx"
age = 18
message = "晚上好 %s,今天你 %s 岁了" % (name,age)
print(message) # 晚上好 xxx,今天你 18 岁了
方式二:通过 f"内容{变量}"
(无法识别类型、无法精度控制)
name = "xxx"
age = 18
cost = 688.88
print(f"message:name = {name},age = {age},cost = {cost}") # message:name = xxx,age = 18,cost = 688.88
数据类型转换
语句(函数) | 说明 |
---|---|
int(x) | 将x转换为整数 |
float(x) | 将x转换为浮点数 |
str(x) | 将x转换成字符串 |
注意:
- 字符串转换成数字类型的前提条件是 内容必须为数字比如"123"
- 浮点数转整数会丢失精度
占位符
%s
:将内容转换成字符串,放入占位位置%d
:将内容转换成整数,放入占位位置%f
:将内容转换成浮点数,放入占位位置
name = "xxx"
age = 18
cost = 688.88
message = "晚上好 %s,今天你 %d 岁了,今晚吃饭花了 %f 元" % (name,age,cost)
print(message) # 控制5宽度 18 ,控制宽度5,小数点后2位 688.88 元,控制小数点后3位688.880 元
数字精度控制
使用符号m.n
来控制数据的宽度和精度
-
m,控制宽度(小数点和小数部分也会计入宽度计算),要求是数据(很少使用),当位数不足m时,会使用空格补齐,设置的宽度小于数字自身的时候不生效
%5d
如果输出数字11,那么就是[空格][空格][空格]11
-
n,控制小数点精度,要求是数字,会进行小数的四舍五入
age = 18
cost = 688.88
message = ("控制5宽度%5d ,控制宽度5,小数点后2位%8.2f 元,控制小数点后3位%.3f 元") % (age,cost,cost)
标识符
标识符命名规则:只允许出现英文、中文、数字、下划线这四类元素
注意:
- 不推荐使用中文命名标识符
- 数字不可开头
- 不可使用关键字
- 大小写敏感
命名规范:
- 命名要简介明了,看到名称就知道是什么意思
- 多个单词组合作为变量名需要使用
_
分隔开来 - 变量中的英文字母使用小写
运算符
算数运算符
运算符 | 描述 | 示例 |
---|---|---|
+ | 加 | a+b |
- | 减 | a-b |
* | 乘 | a*b |
/ | 除 | b/a |
// | 取整除 | 9//2 = 4 , 9.0//2.0 = 4.0 |
% | 取余 | b%a |
** | 指数 | a**b |
赋值运算符
运算符 | 描述 | 示例 |
---|---|---|
= | 赋值运算符 | num = 1 + 2 * 3 |
+= | 加法赋值运算符 | c+=a 等效于 c = c + a |
-= | 减法赋值运算符 | 同上 |
*= | 乘法赋值运算符 | 同上 |
/= | 除法赋值运算符 | 同上 |
%= | 取模赋值运算符 | 同上 |
**= | 幂赋赋值运算符 | 同上 |
//= | 整除赋值运算符 | 同上 |
比较运算符(同JAVA)
运算符 | 描述 |
---|---|
== | 等于 |
!= | 不等于 |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
数据输入
数据输入使用input()
接收,键盘上输入的任何类型数据,获取到的永远是字符串类型
print("你好,你是谁")
name = input()
print("你好," + name)
name = input("你好")
print("你好," + name)
判断语句
if
flag = True
if flag:
flag = False
print(flag) # False
if-else
flag = False
if flag:
flag = True
else:
print(f"flag is {flag} type is {type(flag)}") # flag is False type is <class 'bool'>
if-elif-else
if-elif-else 语句中,各个判断的条件应该是互斥的,因为如果匹配到一个条件就不会往后判断了,elif
可以有多个
number = 100
if number > 100:
print(f"{number} > 100")
elif number < 100:
print(f"{number} < 100")
else:
print(f"{number} = 100")
循环语句
while
number = 5
while number > 0:
print(number)
number -= 1
for
number = "number"
for n in number:
print(n)
range
- range
range(num)
从0到num的数字序列(不包含num) range(2,num)
从 2到num(不包含num)range(2,num,step)
从 2到num(不包含num)step为步长
number = "number"
for n in range(1,10,3):
print(n) # 1 4 7
continue:
continue
结束当前循环进入下一次循环
break:
break
结束break所在的循环
函数
def 函数名(入参)
函数体
return 返回值
def print_hello(name: str):
print(f"Hello {name}")
print_hello("John") # Hello John
def deln(x,b):
return x-b
print(deln(3, 1)) # 2
def sum(a: int, b: int):
return a + b
print(sum(1, 2)) # 3
def sum(a: int, b: int) -> int: # 标识入参类型、返回值类型,当返回值不符合时会警告
return a + b
print(sum(1, 2)) # 3
# 多个返回值,返回值类型不受限制
def test_return():
return 1,"hello",[1,2,3],(1,2,3),{1,2,3},{"a":1,"b":2},True
a,b,c,d,e,f,g = test_return()
print(a,b,c,d,e,f,g) # 1 hello [1, 2, 3] (1, 2, 3) {1, 2, 3} {'a': 1, 'b': 2} True
入参
def user_info(name, age, gender):
print(f"{name} is {age} years old and is {gender}")
user_info("John", 25, "Male") # 位置参数
user_info(name="John", gender="Male", age=25) # 关键字参数
user_info("John", age=25, gender="Male") # 混合参数
# 默认参数
def user_info_2(name, age=18, gender="Male"):
print(f"{name} is {age} years old and is {gender}")
# 如果不传递age 和 gender 那么会按照默认值输出
user_info_2("John") # John is 18 years old and is Male
# 不定长参数,传进的所有参数都会被args变量收集,会根据传入参数的位置合并成一个元组,args是元组类型
def user_info_3(*args):
print(f"{args},type:{type(args)}")
user_info_3("John", "Jay") # ('John', 'Jay'),type:<class 'tuple'>
# 不定长参数,传进的所有参数都会被kwargs变量收集,会根据传入参数的位置合并成一个字典,kwargs是字典类型
def user_info_4(**kwargs):
print(f"{kwargs},type:{type(kwargs)}")
user_info_4(name="John", age=25, gender="Male") # {'name': 'John', 'age': 25, 'gender': 'Male'},type:<class 'dict'>
# 函数也可以作为参数
def user_info_5(name, age, gender):
print(f"{name} is {age} years old and is {gender}")
def user_info_6(func):
func("John", 25, "Male")
user_info_6(user_info_5)
# 这是一种计算逻辑的传递,不是数据的传递
def compute(x,y):
return x+y
def test_func(func):
result = func(1,2)
print(f"func参数类型为:{type(func)}") # func参数类型为:<class 'function'>
return func(1,2)
print(test_func(compute)) # 3
'''
函数作为参数:是将计算逻辑传递给其他函数,而不是数据的实际值。
灵活性:通过传递不同的函数,你可以改变函数的行为,增加代码的灵活性和复用性。
动态行为:函数作为参数使得函数调用可以根据需求动态调整,增强了编程的能力。
'''
def apply_function(func, value):
return func(value)
def square(x):
return x * x
def add(x):
return x + 1
def multiply(x):
return x * 2
result = apply_function(square, 5)
print(result) # 输出 25
print(apply_function(add, 5)) # 输出 6
print(apply_function(multiply, 5)) # 输出 10
匿名函数
使用 lambda
关键字定义匿名函数
- 传入参数表示匿名函数的形参,如:x,y表示接受两个形参
- 函数体只能写一行代码
def apply_function(func, value):
return func(value)
print(apply_function(lambda x: x + x,5)) # 输出 10
数据容器
列表(list)
列表定义通过[元素,元素]
定义,列表元素类型是不受限制的
my_list = ["nihao",666,True,[1,2,3]]
print(my_list) # ['nihao', 666, True, [1, 2, 3]]
print(my_list[-1]) # [1, 2, 3] -1是反向遍历
print(my_list[3]) # [1, 2, 3]
print(my_list[3][1]) # 2
列表的方法
my_list = ["nihao",666,True,[1,2,3]]
n = my_list.index(666) # 查找 值 为 666 的索引下标
my_list.insert(4,888) # 添加元素
print(my_list) # ['nihao', 666, True, [1, 2, 3], 888]
my_list.append(999) # 末尾添加元素
print(my_list) # ['nihao', 666, True, [1, 2, 3], 888, 999]
my_list.pop(4) # 删除指定下标的元素
print(my_list) # ['nihao', 666, True, [1, 2, 3], 999]
my_list.remove(666) # 删除指定元素
print(my_list) # ['nihao', True, [1, 2, 3], 999]
my_list.reverse() # 翻转列表
print(my_list) # [999, [1, 2, 3], True, 'nihao']
my_list.clear() # 清空列表
print(my_list) # []
列表循环遍历
my_list = ["nihao",666,True,[1,2,3]]
for item in my_list:
print(item)
index = 0
while index < len(my_list):
print(my_list[index])
index += 1
元组(tuple)
元组定义通过 (元素,元素)
定义
元组跟列表相同,唯一的区别就是定义完成之后不允许修改(增加、删除元素等)
my_tuple = ("nihao",666,True,[1,2,3])
print(my_tuple) # ('nihao', 666, True, [1, 2, 3])
my_tuple_2 = ("nihao",) # 一个元素的元组 必须要有逗号,不写的话就不是元组类型
print(type(my_tuple_2)) # <class 'tuple'>
my_tuple_3 = ("nihao")
print(type(my_tuple_3)) # <class 'str'>
my_tuple = ("nihao",666,True,[1,2,3])
print(my_tuple.index(666)) # 1 获取666所在的下标
print(my_tuple.count(666)) # 1 获取666出现的次数
#元组元素不允许修改,但是元素内部可以修改
my_tuple = ("nihao",666,True,[1,2,3])
print(my_tuple) # ('nihao', 666, True, [1, 2, 3])
my_tuple[3][0] = 999
print(my_tuple) # ('nihao', 666, True, [999, 2, 3])
# 循环遍历
for item in my_tuple:
print(item)
index = 0
while index < len(my_tuple):
print(my_tuple[index])
index += 1
字符串(str)
字符串可以称为数据容器是因为它可以视作多个字符组成
字符串定义通过""
定义,它同样是不允许修改的数据容器
my_str = "I want to be a multi-millionaire"
print(my_str[0]) # I
print(my_str[-2]) # r 负数表示倒序取值
print(len(my_str)) # 32
print(my_str.index('a')) # 3
print(my_str.count('t')) # 3
my_str2 = my_str.replace('a', '_a_') # 并不是替换,只是得到了新的字符串
print(my_str) # I want to be a multi-millionaire
print(my_str2) # I w_a_nt to be _a_ multi-million_a_ire
str_list = my_str.split(' ') # 根据空格分隔,得到list
print(type(str_list)) # <class 'list'>
print(str_list) # ['I', 'want', 'to', 'be', 'a', 'multi-millionaire']
print(my_str.strip()) # 去掉首尾空格
print(my_str.strip('a')) # 去掉首尾的某个字符
print(my_str.lstrip()) # 去掉左边空格
print(my_str.rstrip()) # 去掉右边空格
print(my_str.startswith('I')) # True 判断字符串是否以指定字符串开头
print(my_str.endswith('aire')) # True 判断字符串是否以指定字符串结尾
print(my_str.find('a')) # 3 找出首次出现a的位置
print(my_str.find('a', 4)) # 7 找出从第4个字符开始首次出现a的位置
print(my_str.find('a', 8)) # -1 从第8个字符开始,没有找到a,返回-1
print(my_str.isalpha()) # False 用于判断字符串是否只包含字母。在这个例子中,它返回 False,说明 my_str 不仅包含字母。
print(my_str.isdigit()) # False 用于判断字符串是否只包含数字。它也返回 False,说明 my_str 不是由数字组成的。
序列(补充)
序列:内容连续、有序、可使用下标的一类数据容器
列表、元组、字符串均可以视为序列
切片
切片:从序列中取出子序列
语法:序列[起始下标:结束下标:步长]
- 步长1表示 一个一个取元素
- 步长2表示 每次从当前起始下标开始取第二个元素
- 步长n表示 每次从当前起始下标开始取第n-1 个元素
- 步长为负数则表示反向取,那么起始下标和结束下标也要对应反过来比如
[10:0:-2]
my_str = "I want to be a multi-millionaire"
my_str_2 = my_str[::-2] # einilmilmae tta
my_str_3 = my_str[::2] # Iwn ob ut-iloar
my_str_4 = my_str[0:10:2] # 从my_str字符串中提取从第0个索引开始,到第10个索引之前,每隔2个字符的子字符串,并将其赋值给my_str_2
集合(set)
set不允许元素重复,内部是无序的,是允许修改的
集合定义通过{}
来定义
my_set = {1, "wan", 2, 3, 3, "nihao"}
print(my_set) # {1, 'wan', 2, 3, 'nihao'}
my_set.add(4) # 添加元素4到集合中
my_set.remove(3) # 从集合中移除元素3,如果3不存在,会引发错误
my_set.discard(3) # 从集合中删除元素3,如果3不存在,不做任何操作
my_set.clear() # 清空集合,移除所有元素
my_set.pop() # 从集合中随机移除并返回一个元素,如果集合为空,会引发错误
my_set2 = my_set.copy() # 复制集合my_set到my_set2
my_set.union({1, 2, 3}) # 将集合{1, 2, 3}与my_set合并,生成一个新的集合
my_set.intersection({1, 2, 3}) # 计算my_set和{1, 2, 3}的交集,生成一个新的集合
my_set.difference({1, 2, 3}) # 计算my_set和{1, 2, 3}的差集,生成一个新的集合
my_set.symmetric_difference({1, 2, 3}) # 计算my_set和{1, 2, 3}的对称差集,生成一个新的集合
my_set.issubset({1, 2, 3}) # 检查my_set是否为{1, 2, 3}的子集
my_set.issuperset({1, 2, 3}) # 检查my_set是否为{1, 2, 3}的超集
字典(dict)
字典定义通过 {key:value,key:value}
来定义,字典的Key是不允许重复的,Key和Value可以是任意数据类型(Key不能是字典)
singer_dict = {
"林俊杰":{
"songs":["愿与愁","交换余生","一千年以后"],
"albums":["乐行者","JJ陆","新地球"]
},
"周杰伦":{
"songs":["七里香","告白气球","发如雪"],
"albums":["范特西","范特西","范特西"]
}
}
'''
singer_dict:{'林俊杰': {'songs': ['愿与愁', '交换余生', '一千年以后'], 'albums': ['乐行者', 'JJ陆', '新地球']},
'周杰伦': {'songs': ['七里香', '告白气球', '发如雪'], 'albums': ['范特西', '范特西', '范特西']}},type:<class 'dict'>
'''
print(f"singer_dict:{singer_dict},type:{type(singer_dict)}")
print(singer_dict["林俊杰"]["songs"]) # ['愿与愁', '交换余生', '一千年以后']
# 新增元素,如果元素不存在则新增,存在则更新
singer_dict["伍佰"] = {"songs":["挪威的森林","泪桥","浪人情歌"],
"albums":["树枝孤鸟","泪桥","双面人"]}
# 更新
singer_dict["周杰伦"] = {"songs":["七里香","告白气球","发如雪"],
"albums":["Jay","范特西","八度空间"]}
# 获取指定key的value 并 删除
singer_dict.pop("伍佰")
# 获取全部key
singer_dict_keys = singer_dict.keys()
# 获取全部value
singer_dict_values = singer_dict.values()
# 获取全部key-value
singer_dict_items = singer_dict.items()
# 遍历字典
for key,value in singer_dict.items():
print(f"key:{key},value:{value}")
# 清空字典
singer_dict.clear()
容器转换
singer_list = ["林俊杰", "周杰伦"]
singer_tuple= ("林俊杰", "周杰伦")
singer_str = "林俊杰,周杰伦"
singer_set = {"林俊杰", "周杰伦"}
singer_dict = {
"林俊杰":{
"songs":["愿与愁","交换余生","一千年以后"],
"albums":["乐行者","JJ陆","新地球"]
},
"周杰伦":{
"songs":["七里香","告白气球","发如雪"],
"albums":["范特西","范特西","范特西"]
}
}
# 转列表
print(f"singer_tuple:list = {list(singer_tuple)}")
print(f"singer_str:list = {list(singer_str)}")
print(f"singer_set:list = {list(singer_set)}")
print(f"singer_dict:list = {list(singer_dict)}")
# 转元组
print(f"singer_list:tuple = {tuple(singer_list)}")
print(f"singer_str:tuple = {tuple(singer_str)}")
print(f"singer_set:tuple = {tuple(singer_set)}")
print(f"singer_dict:tuple = {tuple(singer_dict)}")
# 转集合
print(f"singer_list:set = {set(singer_list)}")
print(f"singer_tuple:set = {set(singer_tuple)}")
print(f"singer_str:set = {set(singer_str)}")
print(f"singer_dict:set = {set(singer_dict)}")
# 转字典需要特殊注意,需要确保每个元素都是包含两个元素的序列
data = [(1, 'a'), (2, 'b')]
my_dict = dict(data) # {1: 'a', 2: 'b'}
文件操作
读取
open(name,mode,encoding)
- name:要打开的文件名称,可以包含文件所在的具体路径
- mode:打开模式:只读(r)、写入(w)、追加(a)等
'r'
:只读模式,文件指针在文件开头。文件必须存在,否则会引发FileNotFoundError
。'w'
:写入模式,文件指针在文件开头。如果文件存在,会覆盖原有内容;如果文件不存在,则会创建新文件。'a'
:追加模式,文件指针在文件末尾。内容会被添加到文件末尾,不会覆盖原有内容;如果文件不存在,则会创建新文件。'b'
:二进制模式,通常与其他模式结合使用,如'rb'
或'wb'
。用于处理二进制文件,如图片或音频文件。'r+'
:读写模式,文件指针在文件开头。既可以读取也可以写入文件;文件必须存在,否则会引发FileNotFoundError
。'w+'
:读写模式,文件指针在文件开头。可以读取和写入文件;文件存在则覆盖原有内容,不存在则创建新文件。'a+'
:读写追加模式,文件指针在文件末尾。可以读取和写入文件,内容追加到文件末尾;文件不存在则创建新文件。
- encoding:编码格式(通常为UTF-8)
"""
test.txt
披萨炸鸡汉堡
泰国新加坡印度尼西亚
蒸桑拿
"""
f = open("C:/Users/user/Desktop/test.txt","r",encoding="utf-8") # 注意:encoding并不是第三位参数,所以这里需要指定参数名
# 打开一个文件之后,对文件的操作都会从上一次操作的位置接着往下
print(type(f)) # <class '_io.TextIOWrapper'>
# read 读取文件,传入的参数为读取的字节数
# print(f.read(5)) # 披萨炸鸡汉
# print(f"read读取全部内容,会根据上次read读取的往下接着读:{f.read()}")
# 读取行内容
#print(f"内容:{f.readline()},readline类型:{type(f.readline())}") # 内容:披萨炸鸡汉堡,readline类型:<class 'str'>
# 读取全部行
#print(f"内容:{f.readlines()},readlines类型:{type(f.readlines())}") # 内容:['披萨炸鸡汉堡\n', '泰国新加坡印度尼西亚\n', '蒸桑拿'],readlines类型:<class 'list'>
# print(f"内容:{f.readline(1)},readline类型:{type(f.readline(1))}") # 内容:披,readline类型:<class 'str'>
# print(f"内容:{f.readlines(1)},readlines类型:{type(f.readlines(1))}") # 内容:['炸鸡汉堡\n'],readlines类型:<class 'list'>
# for循环读取文件
'''
披萨炸鸡汉堡
泰国新加坡印度尼西亚
蒸桑拿
'''
for line in f:
print(line)
# 文件关闭
f.close()
# with open 操作文件,当执行完之后会自动关闭文件占用
with open("C:/Users/user/Desktop/test.txt","r",encoding="utf-8") as f:
for line in f:
print(line)
写入
mode = w
写入模式
# 将内容写入文件,会将内容覆盖,并且是先写入内存中,程序关闭后才会写入硬盘中的文件
# 打开位于桌面的测试文件,以读写模式打开,使用utf-8编码
f = open("C:/Users/user/Desktop/test.txt","w",encoding="utf-8")
# 向文件中写入特定字符串内容
f.write("hello world123")
# 刷新文件内容到磁盘,确保数据立即保存,如果没有执行flush,那么close关闭之后会自动写入到硬盘中
f.flush()
f.close() # 关闭
# with open 操作文件,当执行完之后会自动关闭文件占用
with open("C:/Users/user/Desktop/test.txt","w",encoding="utf-8") as f:
f.write("hello world")
f.write("\n")
f.write("hello world")
mode = a
追加模式
# 追加文件内容,如果存在则会在最后追加内容,不会覆盖,如果不存在则创建文件
f = open("C:/Users/user/Desktop/test.txt","a",encoding="utf-8")
# 向文件中写入特定字符串内容
f.write("hello world123")
# 刷新文件内容到磁盘,确保数据立即保存,如果没有执行这个程序关闭之后会自动写入到硬盘中
f.flush()
f.close() # 关闭
异常
捕获异常
# try捕获异常
try:
print(1 / 0)
except ZeroDivisionError:
# except 可以指定捕获某种异常,也可以默认为空,捕获所有异常或者捕获Exception对象来捕获所有异常
print("除数不能为0")
# try 捕获多个异常
try:
print(1 / 0)
print(a)
except (ZeroDivisionError, NameError) as e:
print(e)
# try except else finally 的使用
try:
a = 1 / 0
except Exception as e:
print(e)
else:
print('没有异常')
finally:
print('不管有没有异常都会执行')
传递性
异常具备传递性
def divide(a, b):
"""尝试除法运算,如果除数为零则抛出异常"""
return a / b
def process_division(x, y):
"""调用 divide 函数,处理可能的异常"""
try:
result = divide(x, y)
print(f"Result: {result}")
except ZeroDivisionError as e:
print(f"Exception caught in process_division: {e}")
# 如果这里没有处理异常,异常会传递到调用者
result = divide(x,y)
def main():
"""调用 process_division,并传递异常"""
try:
process_division(10, 0)
except ZeroDivisionError as e:
print(f"Exception caught in main: {e}")
main()
'''
输出:
Exception caught in process_division: division by zero
Exception caught in main: division by zero
'''
模块
模块 是一个包含 Python 代码的文件。它可以包括函数、类和变量,甚至是可执行的代码。模块的作用是将相关的代码组织在一起,使得程序结构更加清晰。
# 导入模块
import math_utils
print(math_utils.add(1, 2)) # 3
# 导入模块并取别名
import math_utils as mu
print(mu.add(1, 2))
# 导入特定的函数或者变量
from math_utils import add
print(add(1, 2))
# 导入模块所有内容(不推荐使用,可能会导致命名冲突或者不明确的代码)
from math_utils import *
print(add(1, 2))
print(subtract(1, 2))
注意:引入模块的时候会执行模块中的内容
math_util.py
def add(x, y):
return x + y
def subtract(x, y):
return x - y
print(add(1,2))
# 导入模块,此时运行会执行print(add(1,2))输出3
import math_utils
那么如果在模块中需要运行查看结果,又不希望被导入的时候执行,就可以使用__name__
在 Python 中,__name__
是一个特殊的内置变量,用于指示当前模块的名称。它的值会根据模块的执行方式而有所不同:
- 当模块作为主程序运行时:
__name__
的值是'__main__'
。这意味着该模块是被直接执行的主程序。例如,当你直接运行一个 Python 脚本时,这个脚本中的__name__
就会被设为'__main__'
。 - 当模块被导入时:
__name__
的值是模块的名称。即如果你有一个模块example.py
,当你从另一个脚本导入example
时,example
模块的__name__
的值将是'example'
。
这个特性通常用于在模块中编写测试代码或执行代码,但在模块作为库导入时不会执行这些代码。具体做法如下:
# example.py
def main():
print("Running main function")
if __name__ == "__main__":
main()
在这个示例中,当你直接运行 example.py
时,__name__
的值是 '__main__'
,因此会调用 main()
函数。如果你从其他模块导入 example
,__name__
将是 'example'
,因此不会自动执行 main()
函数。
在 Python 中,__all__
是一个特殊的内置变量,用于定义一个模块中哪些对象(如函数、类或变量)应该被导出到外部命名空间。这是特别有用的,当你使用 from module import *
语句从模块中导入所有内容时,__all__
列表中的对象会被导入,而其他对象则不会。
具体用途:
- 控制导出内容:
__all__
用于明确指定哪些对象是公共的,并且可以被模块的用户访问。它可以帮助模块的作者隐藏内部实现细节,只暴露希望用户使用的接口。 - 避免名称冲突:在大模块或包中,
__all__
可以帮助避免不必要的名称冲突或名称污染,只导出特定的名字。
假设有一个模块 mymodule.py
,其中包含几个函数和变量:
# mymodule.py
def public_function():
print("This is a public function")
def _private_function():
print("This is a private function")
__all__ = ['public_function']
在这个示例中,__all__
定义了一个只包含 public_function
的列表,这意味着只有 public_function
会被导出。当你使用 from mymodule import *
导入模块时,只有 public_function
会被导入,而 _private_function
将不会被导入。
使用示例:
# another_script.py
from mymodule import *
public_function() # 这是可以调用的
_private_function() # 这会引发 NameError: name '_private_function' is not defined
包
当模块数量越来越多,就需要使用包来管理模块
在 Python 中,包(Package)是一种组织模块的方式。包是一个包含多个模块(文件)的文件夹,并且包的文件夹下必须包含一个名为 __init__.py
的特殊文件。这个文件可以是空的,也可以包含包的初始化代码。
主要特点和功能:
-
目录结构:
- 包是一个包含模块的目录。目录中必须有一个
__init__.py
文件,这个文件告诉 Python 解释器这是一个包而不是普通目录。Python 3.3 之后,__init__.py
文件可以是空的,但为了兼容性,通常仍然保留这个文件。
- 包是一个包含模块的目录。目录中必须有一个
-
模块导入:
-
通过包,你可以组织多个模块。例如,你可以有一个
mypackage
包,其中包含module1.py
和module2.py
两个模块。你可以这样导入模块:from mypackage import module1
-
你也可以导入包中的特定功能:
from mypackage.module1 import some_function
-
-
子包:
-
包可以包含子包。每个子包也是一个目录,并且也必须包含
__init__.py
文件。例如,mypackage
包可以有一个子包subpackage
,目录结构如下:mypackage/ __init__.py module1.py module2.py subpackage/ __init__.py submodule1.py submodule2.py
-
-
__init__.py
文件:-
__init__.py
文件可以用于初始化包。你可以在这个文件中导入包的常用模块,设置包级别的变量,或执行初始化代码。例如,你可以在mypackage/__init__.py
中添加:from .module1 import some_function
-
这样,你可以直接从包中导入
some_function
:from mypackage import some_function
-
假设有以下目录结构:
mypackage/
__init__.py
module1.py
module2.py
mypackage/module1.py
文件内容:
def function1():
print("This is function1 in module1")
mypackage/module2.py
文件内容:
def function2():
print("This is function2 in module2")
mypackage/__init__.py
文件内容:
from .module1 import function1
现在可以在其他 Python 文件中这样使用:
from mypackage import function1
function1() # 输出: This is function1 in module1
Python 的生态系统非常丰富,不同领域有许多常用的包。以下是一些主要领域中常用的 Python 包:
-
数据分析和科学计算
-
NumPy: 提供支持大规模多维数组和矩阵运算的功能,以及对这些数组进行数学运算的工具。
-
Pandas: 提供高效的数据结构和数据分析工具,特别是 DataFrame 对象。
-
SciPy: 用于科学计算的包,包含许多数学算法和函数,例如优化、积分和插值。
-
Matplotlib: 创建静态、动态和交互式图表的绘图库。
-
Seaborn: 基于 Matplotlib 的统计数据可视化库,提供更加高级的绘图功能。
-
Statsmodels: 用于统计建模和计量经济学分析的库。
-
-
机器学习
-
Scikit-learn: 提供简单易用的机器学习工具,包括分类、回归、聚类和降维算法。
-
TensorFlow: Google 提供的深度学习框架,支持大规模机器学习和神经网络。
-
Keras: 高层神经网络 API,作为 TensorFlow 的前端,使得构建和训练深度学习模型更加简单。
-
PyTorch: 由 Facebook 提供的深度学习框架,支持动态计算图和强大的 GPU 加速。
-
XGBoost: 高效的提升算法库,用于构建精确的预测模型。
-
-
网络请求和API
-
Requests: 简化 HTTP 请求的库,使得网络请求变得更简单和直观。
-
BeautifulSoup: 用于解析 HTML 和 XML 的库,方便进行网页抓取和数据提取。
-
Scrapy: 强大的网络爬虫框架,适用于大规模的数据抓取。
-
httpx: 现代化的 HTTP 客户端,支持异步请求和更多功能。
-
-
Web 开发
-
Flask: 轻量级的 Web 应用框架,提供最小的核心功能,灵活且可扩展。
-
Django: 功能全面的 Web 框架,提供内建的管理后台、数据库支持和其他功能。
-
FastAPI: 现代、快速(高性能)的 Web 框架,用于构建 API,支持异步编程。
-
-
自动化和脚本
-
Selenium: 用于 Web 自动化测试的库,可以控制浏览器执行各种操作。
-
PyAutoGUI: 提供图形用户界面的自动化功能,可以模拟键盘和鼠标操作。
-
Fabric: 用于自动化部署和系统管理的工具,可以帮助管理远程服务器。
-
-
数据库
- SQLAlchemy: 强大的数据库工具,提供 ORM(对象关系映射)功能,并支持多种数据库后端。
- Psycopg2: PostgreSQL 数据库的 Python 客户端库。
- PyMySQL: MySQL 数据库的 Python 客户端库。
可以使用 pip
安装第三方包。在命令行中运行以下命令:
pip install 包名
例如,要安装 requests
包,可以使用:
pip install requests
网速慢的话 可以使用国内的网站进行安装
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple
还可以用Pycharm安装
Json
json
模块是 Python 标准库中的一个模块,用于处理 JSON(JavaScript Object Notation)数据。它可以将 Python 对象编码为 JSON 字符串,也可以将 JSON 字符串解码为 Python 对象。常用的函数包括 json.dumps()
(将 Python 对象转换为 JSON 字符串)和 json.loads()
(将 JSON 字符串转换为 Python 对象)。
import json
data = [
{
"name": "林俊杰",
"age": 30,
"city": "New York"
},
{
"name" : "周杰伦",
"age" : 35,
"city" : "Los Angeles"
}
]
# python 数据格式转换成 Json
json_data = json.dumps(data) # 中文无法正确展示
print(json_data)
json_data = json.dumps(data, ensure_ascii=False) # 不使用ascii码,中文可以正确展示
print(json_data)
# Json 转换成 python 数据格式
s = '[{"name": "林俊杰", "age": 30, "city": "New York"}, {"name": "周杰伦", "age": 35, "city": "Los Angeles"}]'
l = json.loads(s)
print(f"{l},type:{type(l)}")
Pyecharts
Pyecharts 是一个用于生成交互式图表和可视化数据的 Python 库。它基于 ECharts(一个流行的 JavaScript 图表库),提供了简单的接口来创建各种类型的图表,如折线图、柱状图、饼图等。Pyecharts 使得数据可视化变得更加直观和易于使用。
import pyecharts
from pyecharts.charts import Line
# 折线图对象
line = Line()
# 添加x轴数据
line.add_xaxis(["周一", "周二", "周三", "周四", "周五", "周六", "周日"])
# 添加y轴数据
line.add_yaxis("商家A", [1, 2, 3, 4, 5, 6, 7])
# 生成图表
line.render()
运行上面的文件会在项目中生成一个html文件。里面就是我们代码生成的图表
可以通过全局配置来改变折线图的样式
from pyecharts import options as opts
from pyecharts.charts import Line
# 折线图对象
line = Line()
# 添加x轴数据
line.add_xaxis(["周一", "周二", "周三", "周四", "周五", "周六", "周日"])
# 添加y轴数据
line.add_yaxis("商家A", [1, 2, 3, 4, 5, 6, 7])
# 全局配置
line.set_global_opts(
title_opts=opts.TitleOpts(title="折线图示例",pos_left="center",pos_bottom="1%"),
tooltip_opts=opts.TooltipOpts(is_show=True),
legend_opts=opts.LegendOpts(is_show=True),
xaxis_opts=opts.AxisOpts(name="Month"),
yaxis_opts=opts.AxisOpts(name="Sales"),
datazoom_opts=opts.DataZoomOpts(is_show=True)
)
# 生成图表
line.render("line_chart.html")
set_global_opts
:用于设置图表的全局配置。title_opts
:设置图表的标题和副标题。tooltip_opts
:设置悬浮提示框的显示选项。legend_opts
:设置图例的显示选项。xaxis_opts
和yaxis_opts
:设置 X 轴和 Y 轴的属性。datazoom_opts
:添加数据缩放组件,允许用户缩放数据范围。
render
:将图表渲染为 HTML 文件并保存到指定路径。
还可以画地图
# 导入模块
from pyecharts.charts import Map
from pyecharts.options import VisualMapOpts
# 创建Map对象
map = Map()
# 准备数据,包含城市名称及其对应的数值
data = [("北京市", 888), ("广西省", 688), ("湖南省", 886), ("广东省", 1688)]
# 向地图对象中添加数据,指定地图类型、数据和国家代码
map.add("中国地图", data, "china")
map.set_global_opts(
visualmap_opts= VisualMapOpts(
is_show= True,
is_piecewise= True,
pieces=[
{"min": 1000, "label": ">1000", "color": "#7f1818"},
{"min": 800, "max": 999, "label": "500-999", "color": "#ff0000"},
{"min": 600, "max": 799, "label": "100-499", "color": "#ff8c00"},
{"min": 10, "max": 599, "label": "10-99", "color": "#ffff00"},
]
)
)
# 生成HTML文件以可视化地图数据
map.render("chinaMap.html")
类
定义
Python 使用 class
定义类,没有严格的访问修饰符。通常用前导下划线 _
表示保护成员,用双下划线 __
表示私有成员,所有成员默认是公有的。
class Car:
name = None
year = None
_protect_count = 0 # 保护变量
__secret_count = 1 # 私有变量
public_count = 0 # 公开变量
# self 表示 类的 实例,它并不是关键字,可以换做其他名称,self 是一种惯用名称
def __init__(self, name, year):
self.name = name
self.year = year
def __str__(self):
return f"year:{self.year} ,name:{self.name}"
car = Car("Toyota", 2020)
print(car) # year:2020 ,name:Toyota
print(car.name) # Toyota
self 与 cls
在 Python 中,cls
和 self
是两个常见的命名约定,用于在类方法中引用不同的对象。它们的主要区别在于它们所引用的对象类型以及如何使用它们:
self
-
用途:
self
用于实例方法中,引用当前对象的实例。 -
作用: 在实例方法中,
self
是一个指向调用该方法的对象实例的引用。它允许你访问该对象的属性和其他实例方法。 -
用法示例:
class MyClass: def __init__(self, value): self.value = value def show_value(self): print(self.value) obj = MyClass(10) obj.show_value() # 输出: 10
在这个例子中,
self
引用的是obj
实例,self.value
表示obj
实例的value
属性。
cls
-
用途:
cls
用于类方法中,引用类本身,而不是类的实例。 -
作用: 在类方法中,
cls
是一个指向调用该方法的类的引用。它允许你访问类级别的属性和方法,而不是实例级别的。 -
用法示例:
class MyClass: class_variable = 0 @classmethod def increment_class_variable(cls): cls.class_variable += 1 @classmethod def show_class_variable(cls): print(cls.class_variable) MyClass.increment_class_variable() MyClass.show_class_variable() # 输出: 1
在这个例子中,
cls
引用的是MyClass
类,cls.class_variable
表示MyClass
类的类变量。
总结
self
是在实例方法中使用的,用于引用当前对象的实例。cls
是在类方法中使用的,用于引用当前类本身,而不是具体的对象实例。
继承
单继承
# 类定义
class people:
# 定义基本属性
name = ''
age = 0
# 定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
# 定义构造方法
def __init__(self, n, a, w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" % (self.name, self.age))
# 单继承示例
class student(people):
grade = ''
def __init__(self, n, a, w, g):
# 调用父类的构函
people.__init__(self, n, a, w)
self.grade = g
# 覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级" % (self.name, self.age, self.grade))
s = student('ken', 10, 60, 3)
s.speak()
多继承
class people:
# 定义基本属性
name = ''
age = 0
# 定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
# 定义构造方法
def __init__(self, n, a, w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" % (self.name, self.age))
# 单继承示例
class student(people):
grade = ''
def __init__(self, n, a, w, g):
# 调用父类的构函
people.__init__(self, n, a, w)
self.grade = g
# 覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级" % (self.name, self.age, self.grade))
# 另一个类,多继承之前的准备
class speaker():
topic = ''
name = ''
def __init__(self, n, t):
self.name = n
self.topic = t
def speak(self):
print("我叫 %s,我是一个演说家,我演讲的主题是 %s" % (self.name, self.topic))
# 多继承
class sample(speaker, student):
a = ''
def __init__(self, n, a, w, g, t):
student.__init__(self, n, a, w, g)
speaker.__init__(self, n, t)
test = sample("Hzp", 25, 80, 4, "Python")
test.speak() # 方法名同,默认调用的是在括号中参数位置排前父类的方法
重写
class Parent: # 定义父类
def myMethod(self):
print('调用父类方法')
class Child(Parent): # 定义子类
def myMethod(self):
print('调用子类方法')
c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
super(Child, c).myMethod() # 用子类对象调用父类已被覆盖的方法
类的专有方法
__init__ :
构造函数,在生成对象时调用__del__ :
析构函数,释放对象时使用__repr__ :
打印,转换__setitem__ :
按照索引赋值__getitem__:
按照索引获取值__len__:
获得长度__cmp__:
比较运算__call__:
函数调用__add__:
加运算__sub__:
减运算__mul__:
乘运算__truediv__:
除运算__mod__:
求余运算__pow__:
乘
注解
在 Python 中,注解(Annotations)是一种用于为函数参数和返回值提供额外信息的机制。注解并不会影响程序的执行,它们主要用于代码的文档、类型检查和编辑器的自动完成等。
主要用途:
- 类型提示: 注解最常见的用途是提供类型提示(Type Hints)。这有助于开发人员理解函数的参数和返回值的预期类型,从而提高代码的可读性和可维护性。虽然 Python 是动态类型语言,但通过注解可以为静态类型检查工具(如
mypy
)提供支持。 - 文档生成: 注解可以用来自动生成文档,帮助生成更完整的 API 文档,确保函数签名的描述与实际实现一致。
- 编辑器支持: 注解为代码编辑器和 IDE 提供了类型信息,从而能够提供更准确的代码补全和提示功能。
语法示例:
注解的基本语法是使用冒号 :
为函数的参数添加类型信息,并使用箭头 ->
为函数的返回值指定类型。
def greet(name: str) -> str:
return f"Hello, {name}"
在这个例子中:
name: str
表示name
参数应该是一个字符串(str
)。-> str
表示greet
函数的返回值应该是一个字符串(str
)。
更复杂的示例:
注解可以更复杂,也可以使用 Python 的标准库 typing
提供的类型提示功能。例如:
from typing import List, Dict, Optional
def process_data(data: List[Dict[str, Optional[int]]]) -> str:
# data 是一个包含字典的列表,每个字典的值可以是整数或 None
return f"Processed {len(data)} items"
在这个例子中:
data: List[Dict[str, Optional[int]]]
表示data
参数是一个字典列表,其中字典的键是字符串,值可以是整数或None
。-> str
表示函数process_data
返回一个字符串。
Union
允许指定多个可能的类型作为参数或返回值的类型。它在 typing
模块中定义。以下是使用 Union
的示例:
from typing import Union
def process_value(value: Union[int, float, str]) -> str:
if isinstance(value, (int, float)):
return f"Number: {value}"
elif isinstance(value, str):
return f"String: {value}"
else:
raise ValueError("Unsupported type")
# 示例调用
print(process_value(10)) # 输出: Number: 10
print(process_value(3.14)) # 输出: Number: 3.14
print(process_value("hello")) # 输出: String: hello
获取注解:
你可以通过 __annotations__
属性获取函数的注解。这个属性返回一个字典,键是参数名,值是注解。
def greet(name: str, age: int) -> str:
return f"Hello, {name}. You are {age} years old."
print(greet.__annotations__)
输出:
{'name': <class 'str'>, 'age': <class 'int'>, 'return': <class 'str'>}
与JAVA区别
Python 和 Java 中类的一些主要区别:
1. 语法和定义方式
-
Python:
- 使用
class
关键字定义类。 - 不需要显式地声明数据类型。
- 使用缩进来定义代码块。
class Person: def __init__(self, name, age): self.name = name self.age = age def greet(self): print(f"Hello, my name is {self.name} and I am {self.age} years old.")
- 使用
-
Java:
- 使用
class
关键字定义类。 - 需要显式地声明数据类型。
- 使用花括号
{}
来定义代码块。
public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public void greet() { System.out.println("Hello, my name is " + name + " and I am " + age + " years old."); } }
- 使用
2. 继承和多态
-
Python:
- 支持多重继承(一个类可以继承多个父类)。
- 动态类型系统支持运行时多态。
- 不需要显式地声明接口或抽象类,但可以使用
abc
模块来创建抽象基类。
class Animal: def speak(self): pass class Dog(Animal): def speak(self): print("Woof") class Cat(Animal): def speak(self): print("Meow")
-
Java:
- 支持单继承(一个类只能有一个直接父类),但可以实现多个接口。
- 静态类型系统支持编译时多态。
- 使用
interface
关键字定义接口,使用abstract
关键字定义抽象类。
public interface Animal { void speak(); } public class Dog implements Animal { @Override public void speak() { System.out.println("Woof"); } } public class Cat implements Animal { @Override public void speak() { System.out.println("Meow"); } }
3. 访问修饰符
-
Python:
- 没有严格的访问修饰符。通常用前导下划线
_
表示保护成员,用双下划线__
表示私有成员。 - 所有成员默认是公有的。
class MyClass: def __init__(self): self.public_member = 1 self._protected_member = 2 self.__private_member = 3
- 没有严格的访问修饰符。通常用前导下划线
-
Java:
- 使用访问修饰符如
public
,protected
,private
来控制成员的访问权限。 - 默认访问级别为包内可见(即无修饰符时)。
public class MyClass { public int publicMember; protected int protectedMember; private int privateMember; }
- 使用访问修饰符如
4. 构造函数
-
Python:
- 构造函数使用
__init__
方法。
class Person: def __init__(self, name): self.name = name
- 构造函数使用
-
Java:
- 构造函数与类同名。
public class Person { public Person(String name) { // Constructor } }
5. 方法和属性
-
Python:
- 方法和属性没有严格的访问修饰符。
- 支持动态添加和修改方法和属性。
class MyClass: def __init__(self): self.value = 10 def method(self): print(self.value) obj = MyClass() obj.new_attr = 20 # 动态增加新属性
-
Java:
- 方法和属性需要显式声明访问修饰符。
- 不支持动态添加方法或属性(需要通过反射来实现)。
public class MyClass { private int value; public MyClass() { this.value = 10; } public void method() { System.out.println(value); } }
Python 的面向对象编程特性更加灵活和动态,而 Java 的面向对象编程则更为严格和静态。
原文地址:https://blog.csdn.net/weixin_46016309/article/details/142911622
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!