Python介绍
Python是著名的“龟叔”Guido van Rossum在1989年圣诞节期间,为了打发无聊的圣诞节而编写的一个编程语言。龟叔给Python的定位是“优雅”、“明确”、“简单”,所以Python程序看上去总是简单易懂,初学者学Python,不但入门容易,而且将来深入下去,可以编写那些非常非常复杂的程序。
优点:
- Python为我们提供了非常完善的基础代码库,覆盖了网络、文件、GUI、数据库、文本等大量内容,被形象地称作“内置电池(batteries included)”。
缺点:
- 和
C程序相比Python运行非常慢,因为Python是解释型语言,代码在执行时会一行一行地翻译成CPU能理解的机器码,这个翻译过程非常耗时。C程序是运行前直接编译成CPU能执行的机器码,所以非常快。 - Python代码不能加密。发布的Python程序,实际上就是发布源代码,这一点跟C语言不同,
C程序只需把编译后的机器码(xxx.exe)发布出去。从机器码反推出C代码是不可能的,所以,凡是编译型的语言,都没有这个问题,而解释型的语言,则必须把源码发布出去。
python 官方文档:docs.python.org/3.14/
Python安装
Python是跨平台的,在Windows上写Python程序,放到Linux上也是能够运行的。Python解释器(就是负责运行Python程序的),一个命令行交互环境和一个简单的集成开发环境。
Python解释器的下载地址:www.python.org/downloads/
Mac 上安装:Mac 自带的Python版本是2.7。要安装最新的Python 3,有两个方法:
方法一:从Python官网下载Python 3 macOS版的安装程序,下载后双击运行并安装;
方法二:如果安装了Homebrew,直接通过命令brew install python3安装即可。
安装成功如下:
➜ ~ python3
Python 3.13.1 (main, Dec 3 2024, 17:59:52) [Clang 16.0.0 (clang-1600.0.26.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
命令行交互模式
python3命令进入交互模式exit退出交互模式
数据类型、变量
字符串
''、"":只是字符串表示的一种方式
- 有单引号又有双引号:
"I'm OK" - 有转义字符:
'I\'m ok.' r''表示''内部的字符串默认不转义:r'I\'m ok.'- 多行格式
'''...'''print('''java python\n js ''') print(r'''hello,\n world''')
Boolean
只有两种值:True、False 可以参与逻辑运算:and、or和not
print(not(True and False))
print(1 == 1 and 5 > 3 > 1)
age = 9
if age >= 18:
print('adult')
else:
print('teenager')
None
None一个特殊的空值
变量
=可为变量赋值,python中可以将任意数据类型赋值给一个变量,这种变量本身类型不固定的语言称之为动态语言。而与之对应的静态语言在定义变量时必须指定变量类型,如果赋值的时候类型不匹配,就会报错。
常量
常量就是不能变的变量,比如π就是一个常量。在Python中,常量通常全部大写。PI = 3.14159265359
整数和浮点数
Python的整数没有大小限制,某些语言的整数根据其存储长度是有大小限制的,例如Java对32位整数的范围限制在-2147483648-2147483647。
Python的浮点数也没有大小限制,但是超出一定范围就直接表示为inf(无限大)。
除法
Python有两种除法:
/:结果为浮点数
>>> 9 / 3
3.0
//:地板除,两个整数的除法仍然是整数
>>> 10 // 3
3
- 取余
>>> 10 % 3
1
字符串和字符编码
字符串的编码问题
-
ASCII编码
计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字。计算机中
8bit表示1byte,所以一个字节能表示的最大的整数就是255,如果要表示更大的整数,就需要用多个字节表示。比如两个字节可表示的最大整数是65535,4个字节可表示的最大整数是4294967295。最早计算机只有
127个字符(大小写英文字母、数字和一些符号)被编码到计算机里,这个编码表被称为ASCII编码,比如大写字母A的编码是65,小写字母z的编码是122。 -
Unicode 编码
如果要处理中文一个字节显然是不够的,至少需要两个字节,并且不能和ASCII编码冲突,所以,中国制定了
GB2312编码,用来把中文编进去。但是全世界有上百种语言,日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr里,各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。因此,
Unicode字符集应运而生。Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。Unicode最常用的是UCS-16编码,用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。现代操作系统和大多数编程语言都直接支持Unicode。ASCII编码是1个字节,而Unicode编码通常是2个字节。
字符 十进制 二进制的 Unicode编码 A 65 01000001 00000000 01000001 0 48 00110000 00000000 00110000 中 20013 01001110 00101101 01001110 00101101 -
UTF-8
Unicode编码解决了乱码问题。但是存储的文本大多是英文的话,用Unicode编码比ASCII编码需要多一倍的存储空间,在存储和传输上就十分不划算。所以,又出现了把Unicode编码转化为“可变长编码”的UTF-8编码。
UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间:而ASCII编码实际上可以被看成是UTF-8编码的一部分,是可兼容的
| 字符 | ASCII | Unicode | UTF-8 |
|---|---|---|---|
| A | 01000001 | 00000000 01000001 | 01000001 |
| 中 | 01001110 00101101 | 11100100 10111000 10101101 |
在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。
用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件:
浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器:
所以你看到很多网页的源码上会有类似<meta charset="UTF-8" />的信息,表示该网页正是用的UTF-8编码。
Python中的字符串
ord() 和 chr()
Python 3版本中,字符串是以Unicode编码的,也就是说,Python的字符串支持多语言,Python提供了ord()函数获取字符的整数表示,chr()函数把编码转换为对应的字符。也可以使用16进制的方式表示\u4f60 \u597d
var1 = ord("你")
print(var1)
print(chr(var1))
var1 = hex(ord("你"))
var2 = hex(ord("好"))
print(var1, var2)
print("\u4f60 \u597d")
# 运行结果
20320
你
0x4f60 0x597d
你 好
Python字符串类型是str,在内存中以Unicode表示,一个字符对应若干个字节。如果要在网络上传输或保存到磁盘上,则需将str变为以字节为单位的bytes。
bytes类型的数据用带b前缀的单引号或双引号表示;
x = b'ABC'
print(type(x))
# 运行结果
<class 'bytes'>
encode() 和 decode()
encode()编码
var3 = 'ABC'.encode('utf-8')
print(var3)
var3 = 'ABC'.encode('ascii')
print(var3)
var3 = '你好'.encode('utf-8')
print(var3)
var3 = b'ABC'.decode('ascii')
print(var3)
# 运行结果
b'ABC'
b'ABC'
b'\xe4\xbd\xa0\xe5\xa5\xbd'
ABC
decode()解码
var3 = b'ABC'.decode('ascii')
print(var3)
var3 = b'\xe4\xbd\xa0\xe5\xa5\xbd'.decode('utf-8')
print(var3)
# errors='ignore'忽略错误的字节
var3 = b'\xe4\xbd\xa0\xe5\xa5\xff'.decode('utf-8',errors='ignore')
print(var3)
# 运行结果
ABC
你好
你
Python源代码是一个文本文件,所以,在保存源代码时,务必指定保存为UTF-8编码。当Python解释器读取源代码时,为了让它按UTF-8编码读取,我们通常在文件开头写上这两行:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#!/usr/bin/env python3 这是一个 shebang(哈希邦) 行,告诉操作系统如何执行这个文件。
#!表示这是一个 shebang 行。/usr/bin/env是一个命令,用来查找并执行指定的程序。它会找到 Python3 解释器并运行该文件。python3指定使用 Python 3 作为解释器,确保在执行该文件时,使用的是 Python 3 而非 Python 2。
# -*- coding: utf-8 -*- 告诉 Python 解释器该文件使用 UTF-8 编码。
len()
len()字符串长度,如果参数为bytes类型,则计算有多少个字节
print(len('hello'))
print(len('欢迎你,python'))
# len()函数计算的是str的字符数,如果换成bytes,len()函数就计算字节数:1个中文字符经过UTF-8编码后通常会占用3个字节,而1个英文字符只占用1个字节
print(len(b'\xe4\xb8\xad\xe6\x96\x87'))
print(len('中文'.encode('utf-8')))
# 运行结果
5
10
6
6
format
遵循了C语言,% 表示格式化。
| %d | 整数 |
|---|---|
| %f | 浮点数 |
| %s | 字符串 |
| %x | 十六进制整数 |
print('Hello, %s' % 'world')
print('Hi, %s, you have $%d.' % ('Michael', 1000000))
print('%2d-%02d' % (3, 1))
print('%.2f' % 3.1415926)
# 有需要转义的%,`%%`来表示一个`%`
print('growth rate: %d %%' % 7)
运行结果:
Hello, world
Hi, Michael, you have $1000000.
3-01
3.14
growth rate: 7 %
format()
print('恭喜{0}, 成绩提升了 {1:.1f}% !'.format('小明', 17.125))
运行结果:
恭喜 小明, 成绩提升了 17.1% !
f-string:以f开头的字符串,称之为f-string,它和普通字符串不同之处在于,字符串如果包含{xxx},就会以对应的变量替换:
r = 2.5
# ** 的作用是进行幂运算,计算 r 的平方。
s = 3.14 * r ** 2
print(f'The area of a circle with radius {r} is {s:.2f}')
集合类型
list
list 为 python 的一种内置数据类型,是一种有序的集合
classmates = ['Michael', 'Bob', 'Tracy']
print(classmates)
print(len(classmates))
print(classmates[0])
print(classmates[1])
print(classmates[2])
# 数组越界会报错
# print(classmates[3])
print(classmates[-1])
print(classmates[-2])
print(classmates[-3])
classmates.append('Adam')
print(classmates)
classmates.insert(1, 'Jack')
print(classmates)
# 删除list末尾的元素
print(classmates.pop())
print(classmates)
# 删除指定位置的元素
print(classmates.pop(1))
print(classmates)
# list中也可放入不同数据类型
arr = ['Apple', 123, True, ['Michael', 'Bob', 'Tracy']]
print(arr)
print(len(arr))
print(arr[3])
print(arr[3][2])
运行结果:
['Michael', 'Bob', 'Tracy']
3
Michael
Bob
Tracy
Tracy
Bob
Michael
['Michael', 'Bob', 'Tracy', 'Adam']
['Michael', 'Jack', 'Bob', 'Tracy', 'Adam']
Adam
['Michael', 'Jack', 'Bob', 'Tracy']
Jack
['Michael', 'Bob', 'Tracy']
['Apple', 123, True, ['Michael', 'Bob', 'Tracy']]
4
['Michael', 'Bob', 'Tracy']
Tracy
tuple
tuple元组,有序列表和list类似,但是一旦初始化就不可修改,它也没有append(),insert()这样的方法。类似java中的枚举,在定义的时候元素的值已经确定。
weekdays = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday")
print(weekdays[0])
print(weekdays[6])
#定义一个空的tuple
t1 = ()
print(type(t1))
# 定义一个只有1个元素的tuple
# 此处定义的不是tuple,是1这个数!这是因为括号()既可以表示tuple,又可以表示数学公式中的小括号,这就产生了歧义
# Python规定,这种情况下,按小括号进行计算,计算结果自然是1
t1 = (1)
print(type(t1))
# 消除定义一个元组歧义的方式
t1 = (1,)
print(type(t1))
# 定义一个可变的 tuple
# tuple所谓的“不变”是说,指向永远不变
t1 = ('a', 'b', ['A', 'B'])
t1[2].append('C')
print(t1)
运行结果:
Monday
Sunday
<class 'tuple'>
<class 'int'>
<class 'tuple'>
('a', 'b', ['A', 'B', 'C'])
dict
Python内置了字典dict(dictionary),在其他语言中也称为map,使用键-值(key-value)存储;而dict数据结构确实是基于哈希表(hash table)实现的,所以查找速度较快,但却是无序的。
d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
print(d['Michael'])
# 新增元素
d['Adam'] = 67
print(d['Adam'])
# key不存在,dict就会报错
# print(d['Tom'])
# 判断key是否存在
print('Thomas' in d)
# get(),如果key不存在,可以返回None,或者自己指定的value
print(d.get('Thomas'))
print(d.get('Thomas', 10))
# 重新赋值
d['Bob'] = 80
print(d['Bob'])
# 删除一个key
d.pop('Bob')
print('Bob' in d)
set
set无序不重复,和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。
s = {1, 2, 3, 3, 2, 4}
# 自动过滤重复的数字
print(s)
# 加入元素
s.add(5)
print(s)
# 移除元素
s.remove(1)
print(s)
运行结果:
{1, 2, 3, 4}
{1, 2, 3, 4, 5}
{2, 3, 4, 5}
set 的特性无序、无重复则可实现数学意义上的 交集、并集
s1 = {1, 2, 3}
s2 = {2, 3, 4}
# 交集
print(s1 & s2)
# 并集
print(s1 | s2)
运行结果:
{2, 3}
{1, 2, 3, 4}
条件控制语句
if
age = 2
# 判断是True,执行缩进的语句
if age >= 18:
print('your age is', age)
print('adult')
elif age < 4:
print('your age is', age)
print('baby')
else:
print('your age is', age)
print('teenager')
运行结果
your age is 2
baby
非零数值、非空字符串、非空list等,就判断为True,否则为False
if 33:
print('True')
t = ()
if t:
print('True')
else:
print('False')
print(input("if======================="))
运行结果:
True
False
case
score = 'B'
match score:
case 'A':
print('score is A.')
case 'B':
print('score is B.')
case 'C':
print('score is C.')
case _: # _表示匹配到其他任何情况
print('score is ???.')
age = 9
match age:
# 表示当age < 10成立时匹配,且赋值给变量x
case x if x < 10:
print(f'< 10 years old: {x}')
# 单值匹配
case 10:
print('10 years old.')
# 匹配多个值
case 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18:
print('11~18 years old.')
case 19:
print('19 years old.')
case _:
print('not sure.')
args = ['gcc', 'hello.c', 'world.c']
# args = ['clean']
# args = ['gcc']
match args:
# 如果仅出现gcc,报错:
case ['gcc']:
print('gcc: missing source file(s).')
# 第一个字符串是gcc,第二个字符串绑定到变量file,后面的任意个字符串绑定到*files
case ['gcc', file, *files]:
print('gcc compile: ' + file + ', ' + ', '.join(files))
# 仅出现clean:
case ['clean']:
print('clean')
case _:
print('invalid command.')
for-in
names = ['Michael', 'Bob', 'Tracy']
for name in names:
print(name)
#生成0-4的列表
list(range(5))
total = 0
for x in range(101):
total = total + x
print(total)
while
total = 0
n = 99
while n > 0:
total = total + n
n = n - 2
print(total)
break 和 continue
n = 1
while n <= 100:
if n > 10:
break # break语句会结束当前循环
if n % 2 == 0:
n = n + 1
continue # continue语句会直接继续下一轮循环,后续的print()语句不会执行
print(n)
n = n + 1
print('END')
函数
函数的定义
Python的内置函数:docs.python.org/3/library/f…
函数的定义:def关键字、函数名、括号、括号中的参数和冒号:,在缩进块中编写函数体,return函数返回值。如果没有return语句,函数执行完毕后也会返回结果,只是结果为None。return None可以简写为return
在Function.py文件中定义函数
def my_abs(x):
# 检查参数类型,只允许整数和浮点数类型的参数
if not isinstance(x, (int, float)):
raise TypeError('bad operand type')
if x >= 0:
return x
else:
return -x
print(my_abs(-99))
导入函数使用
from Function import my_abs
my_abs(10)
定义空函数,使用pass关键字,表示什么都不做,一般用来做占位符,比如现在还没想好怎么写,先写一个pass让程序能正常运行。
def nop():
pass
python 可以返回多个值,但其实Python函数返回的是仍然只是一个tuple值
import math
def move(x, y, step, angle=0):
nx = x + step * math.cos(angle)
ny = y - step * math.sin(angle)
return nx, ny
函数参数
Python函数定义灵活性比较大除了必选参数外,还可以使用默认参数、可变参数和关键字参数
默认参数
定义默认参数,必选参数在前,默认参数在后;n=2 没有传默认就是2;
def power(x, n=2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
可变参数
可变参数的定义,参数前面加*号。在函数内部,参数numbers接收到的是一个tuple,因此,函数代码完全不变。但调用该函数时,可以传入任意个参数,包括0个参数:
def calc(*numbers):
total = 0
for n in numbers:
total = total + n * n
return total
print(calc(1, 2, 3))
将一个list或者tuple作为可变参数,*nums表示把nums这个list的所有元素作为可变参数传进去。
# 将一个tuple或者一个list作为参数
nums = [1, 2, 3]
print(calc(*nums))
关键字参数
可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
person('张三',18)
person('张三',18, hobby='吃', job='Engineer')
将一个dict作为参数
extra = {'city': 'Beijing', 'job': 'Engineer'}
person('Jack', 24, city=extra['city'], job=extra['job'])
# `**extra`表示把extra这个dict的所有key-value用关键字参数传入到函数的**kw参数,
# kw将获得一个dict,注意kw获得的dict是extra的一份拷贝,
# 对kw的改动不会影响到函数外的extra。
person('Jack', 24, **extra)
命名关键字参数
关键字参数,函数的调用者可以传入任意不受限制的关键字参数。至于到底传了什么,就需要在函数内部通过kw检查。
def person(name, age, **kw):
if 'city' in kw:
# 有city参数
pass
if 'job' in kw:
# 有job参数
pass
print('name:', name, 'age:', age, 'other:', kw)
命名关键字参数可限制关键字参数的名字,例如,只接收city和job作为关键字参数。*作为特殊分隔符,后面的参数被视为命名关键字参数
def person(name, age, *, city, job):
print(name, age, city, job)
如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了
def person(name, age, *args, city, job):
print(name, age, *args, city, job)
person("李四", 22, 'hz', 'd', city='beijing', job='doctor')
命名关键字有默认值,调用时则可无需传递
def person(name, age, *, city='Beijing', job):
print(name, age, city, job)
person('Jack', 24, job='Engineer')
参数组合
在Python中定义函数参数可以组合使用,但其顺序必须是,必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
# 参数的组合
def f1(a, b, c=0, *args, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
# 参数的调用
f1('hello', 'world', 'haha', 'hehe', 'heihei', sex='man', age=10)
# 通过tuple和dict的方式调用
args = (1, 2, 3, 4)
person = {'sex': 'man', 'age': 10}
f1('hello', 'world', *args, **person)