Python修养1

Python修养1

  • 思想:

    • 换行当;

    • 缩进当{}

    • 对象三属性

      • 值: 可变/不可变
      • 身份: 内存唯一地址,严格只读
      • 类型( 可用type(you_want)来读取)
    • 每个变量都相当于指向某个对象的引用

      引用对象可变, 则可以通过变量修改

      引用对象不可变,则只能让变量指向另一个新对象

      image-20260506195354560

  • 关于注释:

    • 单行#
    • 多行command+/
  • 关于赋值的随意性

    s1,s2,s4,s3=s4,s3,s2,s1

  • 关于变量

    • 不需声明, 使用前必须赋值

    • 类型可变

    • 没有double( 或者说double就叫float), 多了complextupledict, stringstr, 列表叫list ——类型名相当于类名

      1
      2
      a=str()
      b=1+2j
    • 元组本身不可变, 但是⚠️其中可变对象元素仍可变

  • 关于运算符

    **表示幂运算

  • 关于布尔类型

    • 注意是TrueFalse, 大小写有规范

    • 0str tuple list dist相当于False ( 但不是等于)

      1
      2
      3
      4
      5
      6
      7
      8
      if not ():
      print ("ok") # ok
      if not {}:
      print ("ok") # ok
      if not "":
      print ("ok") # ok
      if not []:
      print ("ok") # ok
    • True可以看作1, False可以看作0

    1
    2
    3
    4
    5
    6
    True == 1 #True
    False == 0 #True
    "" == False #False
    2 == True #False
    [] == False #False
    [2,3] == True #False
  • 关于逻辑运算符

    注意是andornot

  • 关于类型转换函数

    • ⚠️repr(x)将x转换为字符串表达式, 注意类型是字符串

    • chr(x)将x转换为对应ASCII码字符

      ord(x)将字符转换为整数编码值(16位)

      1
      2
      3
      print(repr(12.334)) # 12.334 
      print(str("hello")) # hello
      print(repr("hello")) # 'hello'
    • 列表和字符串的转换

      语法: <str> = <separator>.join(<list>)

      1
      2
      3
      4
      5
      newstr = list('abcdafg')
      print(newstr) # ['a', 'b', 'c', 'd', 'a', 'f', 'g']
      newstr[4] = 'e'
      str = ''.join(newstr) #列表到字符串转换
      print(str) # abcdefg
    • int(x)不会把x变成整数

    • ⚠️eval(x)把字符串x看做一个表达式求其值

      理想情况下

      eval(repr(x))=x

关于运算符

  • 运算符中只要有一个操作数是小数结果就是小数, 若需要结果整数, 需要额外强制转换

  • 使用/即使整除也是浮点数

  • //整除向下取整,而非向零(c++向0)

关于循环

1
2
3
4
for <变量> in <序列>:
<语句组>
else:
<语句组>
1
2
3
4
while <逻辑表达式>:
<语句组>
else:
<语句组>
  • 没有switch
  • <序列>可用range生成
  • pass表示什么都不做, 占位; continuebreak同用

关于print

print(s,end=" ") 缺省情况end='\n'

简单构造字符串: “xxxx %s xxxx %(s)”

关于is和==的区别

  • a is bTrue说明a和b指向同一个地方
  • a==bTrue则说明放的东西相同,不一定指向同一个地方

a=b使得a和b指向同一个地方

⚠️一般需要:

  • ==比较值

  • is比较是否同一个对象

    =会导致变量别名, ⚠️一个赋值给另一个, 两个变量将指向同一个对象, 修改任何一个都会影响另一个

为了复用同一个对象, 常常有驻留, is难预测→对于**不可变类型只需关注==, 不得用is判断值是否相等 **

推荐使用is的场景

if x is None

小整数有缓存机制, 元组一般没有驻留( 小整数可能会)

关于整数类型

任意长

  • 0b前缀表示进制
  • 0o前缀表示进制
  • 0x前缀表示十六进制

可以使用例如12.99.is_integer()来判断是否整数

查询是否是某个类型

isinstance(<变量名>,<type>)

关于浮点数相等的判断

⚠️用equal_float判断

1
2
3
4
5
import sys
def equal_float(a,b):
return abs(a-b) <= sys.float_info.epsilon
#最小浮点数间隔,32位机为 2e-16
print(equal_float(0.3,0.1+0.2))

想看看sys.float_info

可以

1
2
import sys
print(sys.float_info)

此外

1
2
3
4
5
6
import math
x = 123.50
print(round(x)) #不精确,如print(round(119.49999999999999999)) => 120
print(math.floor(x))
print(math.ceil(x))
print(12.3.is_integer())

关于输入和输出

  • 关于input(<问候语>)

    • 输出问候语, 读取输入的字符串, 需要强制类型转换才能当数字用
  • 一行多输入

    1
    2
    3
    4
    5
    lst=input().split()
    x,y,z=int(lst[0]),lst[1],int(lst[2])
    # x,z是整数,y是字符串
    # ...
    # split函数内部可以指定分割符如",."表示以",."为分割符而⚠️不是其中任意字符

    split(s)开头和结尾有非缺省分割符的字符串列表会额外输出空串

    ( 缺省情况下智能合并连续分割符忽略开头和结尾分割符)

  • 输入输出的重定向

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import sys
    f=open("t.txt","r")
    g=open("d.txt","w")
    sys.stdin=f
    sys.stdout=g
    s=input()
    print(s)
    f.close()
    g.close()

关于字符串

  • *可以构成重复字符串

⚠️重点

赋值

单引号\双引号\三引号 皆可

其中三双引号可以包含换行符\制表符\特殊符号

  • 字符串太长

    1
    2
    3
    print("this \
    is \
    good")

    太长了使用()\

    1
    2
    3
    4
    5
    6
    if a>3 and \
    a<9:
    print('ok')
    if(a>3 and
    a<9):
    print('ok')

访问

变量[序号或切片]访问子串

完成切片语法

x[start:stop:step]

1
2
3
4
5
6
x="aggfdfd"
print(x[-3:-1])
print("hhh"[2])
print(x[-1:])
print(x[:])
print(::-1) # 反转字符串

⚠️字符串是不可修改的

如果确实需要,应先转换为列表

1
2
3
4
5
6
7
s = list("abc")   # ['a', 'b', 'c']
s[0] = "z" # 可以改
"".join(s) # "zbc"

#否则
s="kskksk"
s[1]="d" #error

输出不转义字符

print(r'ab\ncd')

判断子串

in

not in

正常语言即可

print("hello" in s)

字符串函数

  • count求解子串出现次数

  • len求解字符串长度

  • 其他的

    • s.upper(), s.lower(), s.isdigit()(是否全为数字)
    • s.startwith(), s.endwith()
    • s.find(want)找不到返回-1,s.index(want)抛出异常
    • s.replace(target_index,replacement)
  • s.strip(s) 除去两端空格, \r , \t , \n

    • s.lstrip(s)除左端

    • s.rstrip(s)除右端

      s缺省情况下为空白字符, 指定情况下为s中的所有字符

用多个字符分割

格式:

re.split(pattern,string)

pattern: 匹配的正则表达式

string: 要匹配的字符串

1
2
3
4
import re
a="Beautiful, is; better*than\nugly"
print(re.split(';| |,|\*|\n',a))
# ['Beautiful', '', 'is', '', 'better', 'than', 'ugly']

正则 ;| |,|\*|\n 表示遇到 分号、空格、逗号、星号、换行 都要切一刀。

字符串的编码在内存中的编码是unicode的。没有字符类型

1
2
3
4
print(ord("a"))
print(ord("好"))
print(chr(22900))
print(chr(97))

🌊以下为AI整理, 若有时间需勤加复习

字符串格式化

1
2
3
4
5
6
7
8
9
10
# % 格式化: %s字符串 %d整数 %f浮点数 %.nf保留n位小数
print("My name is %s, I am %.2fm tall." % ("tom", 1.746))
print("My age is %d." % 18)
print("%d%s" % (18, "hello"))

# format方法: {序号:宽度.精度.类型}
x = "Hello {0} {1:10}, you get ${2:0.4f}".format("Mr.", "Jack", 3.2)
# > 右对齐, < 左对齐, ^ 中对齐
x = "Hello {0} {1:>10}, you get ${2:0.4f}".format("Mr.", "Jack", 3.2)
x = "Hello {0} {1:^10}, you get ${2:0.4f}".format("Mr.", "Jack", 3.2)

⚠️**%.nf 不是四舍五入,是"四舍六入五成双"**

  • ≤4 舍去,≥6 进一
  • 5 看前面数字奇偶:前为奇则进,前为偶则舍;5后面还有有效数字则一定进
1
2
3
4
print("%.2f, %.2f" % (5.225, 5.325))  # 5.22, 5.33
print("%.1f" % 1.15) # 1.2
print("%.1f" % 1.25) # 1.2 (2是偶数,舍)
print("%.1f" % 1.25012) # 1.3 (5后面还有数,进)

关于字符编码

  • ASCII:1字节,只表示英文、数字、标点(如 'a'0x61
  • GB2312/GBK:兼容ASCII,中文用2个最高位为1的字节表示
  • Unicode:内存编码,几乎涵盖所有文字,每个字符2字节(个别4字节);Python字符串即Unicode
  • UTF-8可变长(1-6字节),英文1字节、中文通常3字节;文件存储/网络传输一般用UTF-8
1
2
3
print(ord('好'))   # 22920  Unicode码点
print(ord('a')) # 97
print(chr(22920)) # 好

⚠️UTF-8文件开头可能有3字节标记 BOMEF BB BF),记事本能正常显示,但Ccin 读取会出错。C需用 _wfopen(L"utf8.txt", L"r,ccs=utf-8") 之类方式读取。


关于字符串与字节流

Python字符串是Unicode,要保存到文件或发送需编码为字节流;读取时自动/手动解码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
s = 'ABC好的'

# 编码为字节流
bs = s.encode('utf-8')
print(bs) # b'ABC\xe5\xa5\xbd\xe7\x9a\x84'
print(len(bs)) # 9 (中文3字节×2 + 英文1字节×3)

bs = s.encode('gbk')
print(len(bs)) # 7 (中文2字节×2 + 英文1字节×3)

# 另一种写法
bs = bytes('ABC好的', encoding='gbk')

# 解码回字符串
s = str(bs, encoding='utf-8') # ABC好的
print(str(b'abc\xe5\xa5\xbd\xe7\x9a\x84', encoding='utf-8')) # abc好的

关于源程序编码

Python 3 默认认为 .py 源文件是 UTF-8 编码(且期望有BOM)。如果源文件实际是GBK且无编码声明,运行报错:

1
SyntaxError: Non-UTF-8 code starting with '\xb7' in file testansi.py...

解决办法:在源文件第一行或第二行加声明

1
# -*- coding: GBK -*-

PyCharm编写的 .py 文件默认就是UTF-8,一般无需额外声明。


C++与Python字符串对比

特性C++ std::stringPython str
可变性可变(可直接改 s[0]='H'不可变(修改需创建新对象)
越界访问需手动注意,可能崩溃自动抛异常
引号双引号(单引号是char单/双/三引号均可
Unicodestd::wstring或第三方库原生支持
空值""""None
性能直接操作内存,快因不可变性+GC稍慢,但开发效率高

操作语法差异:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 初始化
s1 = "hello"
s2 = 'a' * 5 # C++: string s2(5, 'a')

# 长度
len1 = len(s1) # C++: s1.size() 或 s1.length()

# 拼接
s3 = s1 + " " + s2 # 同C++,但Python不可变,结果是新对象

# 访问
c = s1[0] # 同C++,但 s1[0] = 'H' 会报错!

# 比较
is_equal = (s1 == s2) # 同C++
is_less = (s1 > s2) # 同C++,按字典序
result = (s1 > s2) - (s1 < s2) # C++: s1.compare(s2) 返回1/0/-1

# 交换
s1, s2 = s2, s1 # C++: swap(s1, s2)

# 切片/子串
sub = s1[1:4] # "ell" 左闭右开;C++: s1.substr(1, 3)

# 查找
pos = s1.find("ell") # 返回索引或-1;C++: 返回索引或 string::npos

# 替换
s1 = s1.replace("ell", "ipp") # ⚠️返回新字符串!C++: s1.replace(1,3,"ipp")原地改

# 字符串↔数字
num = int("123") # C++: stoi(s)
s1 = str(123) # C++: to_string(num)
f = float("3.14") # C++: stof(s)
s1 = str(3.14) # C++: to_string(f)