Python—基础(1)

294 阅读17分钟

Python介绍

Python是著名的“龟叔”Guido van Rossum在1989年圣诞节期间,为了打发无聊的圣诞节而编写的一个编程语言。龟叔给Python的定位是“优雅”、“明确”、“简单”,所以Python程序看上去总是简单易懂,初学者学Python,不但入门容易,而且将来深入下去,可以编写那些非常非常复杂的程序。

image.png

优点:

  • 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 退出交互模式

image.png

数据类型、变量

字符串

''"":只是字符串表示的一种方式

  1. 有单引号又有双引号:"I'm OK"
  2. 有转义字符:'I\'m ok.'
  3. r''表示''内部的字符串默认不转义:r'I\'m ok.'
  4. 多行格式'''...'''
    print('''java
        python\n
        js
    ''')
    print(r'''hello,\n
    world''')
    

Boolean

只有两种值:True、False 可以参与逻辑运算:andornot

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编码
    A650100000100000000 01000001
    0480011000000000000 00110000
    2001301001110 0010110101001110 00101101
  • UTF-8

Unicode编码解决了乱码问题。但是存储的文本大多是英文的话,用Unicode编码比ASCII编码需要多一倍的存储空间,在存储和传输上就十分不划算。所以,又出现了把Unicode编码转化为“可变长编码”的UTF-8编码

UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间:而ASCII编码实际上可以被看成是UTF-8编码的一部分,是可兼容的

字符ASCIIUnicodeUTF-8
A0100000100000000 0100000101000001
01001110 0010110111100100 10111000 10101101

在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。

用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件:

image.png

浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器:

image.png

所以你看到很多网页的源码上会有类似<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")
# 运行结果
203200x4f60 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)

breakcontinue

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语句,函数执行完毕后也会返回结果,只是结果为Nonereturn 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)

命名关键字参数可限制关键字参数的名字,例如,只接收cityjob作为关键字参数。*作为特殊分隔符,后面的参数被视为命名关键字参数

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)