Python基础补全

本文介绍了Python的基础知识,包括安装Anaconda、基础语法如内置关键字、字符串格式化、循环与条件语句,以及数据类型如数字、字符串、列表、元组、字典和集合。还涉及了函数的使用、装饰器的概念、类与对象以及命名空间和闭包的原理。
摘要由CSDN通过智能技术生成

搭建环境

下载anaconda: https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/?C=M&O=D
安装:https://blog.csdn.net/HowieXue/article/details/118442904

基础语法

查看内置关键字:

import builtins
print(dir(builtins))

输出:
print(*objects,sep='',end='\n',file=sys.stdout,flush=False)

with open("./abc.txt",'w') as f:
    print(12345,file=f)	#把12345直接写入abc.txt文件

print('hello','peter',sep='-and-',end="--end")
#hello-and-peter--end

for i in range(10):
    print('.',end='',flush=True)
    time.sleep(0.3)

输入:
input([prompt])

name = input("input ur name:")
print(name,"nice to meet u",sep=',')

#返回的是字符串
str = input("input nums like 1,2,3").split(',')

标准数据类型

  1. 数字(Number): 不可变, 非序列
    1. int([x],base=10)
    2. complex([real[,imag]])
  2. 字符串(String): 不可变, 是序列
    1. 单行字符串
    2. 多行字符串: 一对三引号定义
    3. Raw原始字符串: 取消转义. print(r"http:\\google.com\n")其中的"\" "\n"不进行转义
    4. 字符串格式化_%: %s, %d, %f, %e, %c, %o, %x, %g
      1. print("%s,%d,%f" % ("str",123,1.23))
    5. 字符串格式化_format: {name}.format(name=" ")
    6. 字符串格式化_f-string: print(f"{name}")
    7. 字符串类方法: replace, endswith, split, join(iterable), find, …
      1. https://www.runoob.com/python/python-strings.html
  3. 列表(List): 可变,是序列
    1. list([iterable])
    2. 对象方法: append(单元素), expend(iterable), sort, sorted(iterable,[fun],reverse=False), reverse
  4. 元组(Tuple): 不可变, 序列
    1. 括号可加可不加
    2. tuple不可变,但其中的列表是可变的
    3. 元组对象方法: count(x), index
  5. 字典(Dictionary): 可变,不是序列
    1. 键和值都为不可变类型
    2. {}创建空字典
    3. 字典的迭代只返回 键
    4. 方法: keys, values, 注意list(d.keys()), get(key,default=None), update([other])
    5. 遍历方式
dic = {'a':123,'b':23,'c':56}
total = 0
#方式1
for k in dic: #默认遍历键
    v = dic[k]
    if type(v) in (int,float,bool,complex): #判断是否为数值类型
        total += v #累加
print(total)

#方式2
for k,v in dic.items():
    k,v
  1. 集合(Set): 可变, 非序列
    1. 无序,不重复
    2. 元素必须为不可变类型
    3. frozenset 不可变的set
    4. 集合的符号运算: 包含于<=, 差集-, 并集|, 交集&, 外集^
    5. 方法: issubset, issuperset, union, intersection, difference, symmetric_difference, add, discard
  2. 序列的索引和切片:
    1. 切片: [起始索引: 结束索引: 步长]
    2. 若步长为负,则从后面开始切片,索引依次做减法. [::-1]
    3. 索引会降维,切片不会降维
  3. del 语句
    1. del 删除变量时,不直接删除数据,而是解除变量对数据的引用,当数据引用计数为0时,则系统回收他.
a = [1,2,3,4]
del a[0]
print(a) #[2,3,4]

赋值&拷贝

  1. 赋值:
    1. id(object): 返回object的唯一标识符(内存地址)
    2. 当执行a=99时,内存先开辟空间存放99,然后定义变量名a来指定这个空间的内存地址. python中的赋值语句不复制对象,只是建立引用关联.
    3. 小整数对象池: 为优化速度,范围在[-5,256]之间的数字是预存的
    4. 一个值可以被多个变量名引用,当变量值的引用计数为0时便会被回收.
    5. 当一个可变类型的数据被多个变量名引用时,如果对该原数据进行修改,那么它的所有引用都会改变
  2. 浅拷贝
    1. 浅层拷贝只考虑最外层的数据类型
    2. 如果最外层的数据类型是可变的(比如列表),则(最外层)发生拷贝
    3. 如果最外层的数据类型是不可变的(比如元组),则不发生拷贝
  3. 深拷贝
    1. 如果判断的该数据本身不可变,且包含的所有数据都不可变,则该数据不发生拷贝
    2. 如果判断的该数据本身可变,或者包含的数据存在可变,则该数据(可变的数据)发生拷贝

运算符

  1. 算数运算符: +, -, *, /, %, **幂, //向下取整
  2. 比较运算符
  3. 赋值运算符:
    1. 海象赋值运算符’:=’ 可在表达式内部为变量赋值
    2. 增强赋值: 如可变类型的追加赋值+=
    3. 序列赋值: a,b = 3,4
    4. 多目标赋值: a = b = c = [1,2,3]
  4. 逻辑运算符: 优先级: not > and > or
    1. all(iterable):如果iterable的所有元素全为真值或iterable为空则返回True
    2. any(iterable) :任一元素为真则True, 若可迭代对象为空,则返回False如 any([False,None,0])
    3. 短路原则: 如果前面的部分已经计算出整个表达式的结果,则后面的部分不再计算.
  5. 成员运算符: in, not in, 判断对象中是否存在某个元素
  6. 身份运算符: is, is not, 判断两个标识符是不是引用同个或不同对象 如id(a)==id(b)
  7. 位运算符
  8. 运算符优先级
  9. 连接操作 : 可以对字符串,列表,元组进行连接操作
    1. +: 合并成新序列
    2. +=: 原地合并
    3. *n: 重复n次

条件,循环,推导式

  1. 三元表达式: True值 if 条件 else False值
  2. while … else … : while执行完毕执行else,注意在break后else不执行
count = 0
while count<10:
    count+=1
    if(count>5):
        break #若break执行则else语句不执行
        pass
    print(count)
else:
    print('count>10')
  1. 确定次数用for循环,不确定次数则使用while循环
  2. for循环:
    1. for 变量 in 可迭代对象(或迭代器):
      1. 遍历获取元素: for i in list
      2. 遍历获取索引: range(len(list))
      3. 遍历获取元素和索引(枚举) enumerate(iterable,start=0): 将索引和元素组成一个元组,返回的是迭代器。注意用list迭代第二次会出来空列表。
      4. 循环确定次数:for _ in range(num)
    2. for … in … else: else后的东西在for循环结束后执行 若当中break则不执行
    3. 注意for循环中不可以用来删除元素或添加元素,不能改变列表大小
list1 = [1,2,3,4]
new_list = list1.copy() #list1[:],list(list1)
for i in new_list:
    list1.remove(i)
  1. 字典和集合遍历删除问题:
d = {'name':'Tony','age':28,'height':180}
for k in d:
    print(d.pop(k))
    print(d)
#一定要保证在迭代期间,字典和集合的size不变,不然则报错

new_d = d.copy() 
#d.[:]不可以, d.keys()不可以视图同原字典改变, list(d)获取新的键列表
for k in new_d:
    print(d.pop(k))
  1. 推导式
    1. 列表推导式
      1. [ 含参表达式 for 子句 其他多个for子句或if子句]
      2. 嵌套列表推导式: [ [列表推导式] for 子句 其他多个for子句或if子句]
list1 = [i**2 for i in range(6) if i%2]
print(list1)

#全等于
list2 = []
for i in range(6):
    if i%2: #当为奇数时
        list2.append(i**2)
print(list2)

'''
[1, 9, 25]
[1, 9, 25]
'''

#嵌套列表
mat = [  [1,2,3,4],
         [5,6,7,8],
         [9,10,11,12] ]
print(mat)

#不利用推导式进行转置
res=[]
for index in range(len(mat[0])):
    list1=[]
    for i in mat:
        list1.append(i[index])
    res.append(list1)
print(res)

#利用推导式进行转置
#根据上面对比一下
res1 = [[i[index] for i in mat] for index in range(len(mat[0]))]
print(res1)
  1. 字典推导式
    1. {k: v for 子句 其他多个for子句或if子句}
    2. 注意键不能重复,重复则覆盖最后一个值
dic = {x:y for x in range(6) for y in range(7,9)}
print(dic)
'''
{0: 8, 1: 8, 2: 8, 3: 8, 4: 8, 5: 8}
'''
  1. 集合推导式:
    1. 注意重复项
    2. 不能嵌套,因为不能添加可变元素
s = {i+j for x in range(4,0,-1) for y in range(4)}
print(s)
'''
{1, 2, 3, 4, 5, 6, 7}
'''

函数

  1. 函数文档注释和帮助
    1. 在函数中写入详细描述注释 以 三个单双引号对 括起来
    2. 可以使用函数的 __doc__属性和内置函数help([object])打印查看
def my_abs(x):
    """Return the absolute value of the argument."""
    return x if x > 0 else -x
# 文档注释存放在 __doc__ 属性中
print(my_abs.__doc__)
print()
help(my_abs)

'''
Return the absolute value of the argument.

Help on function my_abs in module __main__:

my_abs(x)
    Return the absolute value of the argument.
'''
  1. 类型标注
    1. 参数内标注 以冒号+类型表达,函数的返回值标注,以->类型 表达
    2. 标注以字典的形式存放在函数的 __annotations属性中
    3. 函数作为参数的类型标注为 Callable[[函数参数], 返回类型]
def func(a: int, b: str, c: list, d: tuple, e: dict, f:
set) -> tuple:
    return a, b, c, d, e, f
print(func(1, 2, 3, 4, 5, 6))
print(func(1, "2", [3], (4, ), {5: 5}, {6}))
print(func.__annotations__)

'''
(1, 2, 3, 4, 5, 6)
(1, '2', [3], (4,), {5: 5}, {6})
{'a': <class 'int'>, 'b': <class 'str'>, 'c': <class 'list'>, 'd': <class 'tuple'>, 'e': <class 'dict'>, 'f': <class 'set'>, 'return': <class 'tuple'>}
'''

#多种类型
def func(a: Union[str,list,set]):
    pass

#函数参数
def my_sort(a: list, f: Callable[[int], int], c: bool):
	return sorted(a, key=f, reverse=c)
print(my_sort([1, -3, 2], abs, True))
  1. 参数分类
    1. 位置参数
    2. 关键字参数
    3. 默认参数
    4. 不定长参数
      1. *args:将参数打包成元组给函数体调用,没有值传给它,就是个空元组
      2. **kwargs:将参数打包成字典给函数体调用,没有值传给它,就是个空字典
      3. 参数顺序固定:当必需参数,*arg参数,**kwargs参数同时存在时,它们的顺序是固定的,否则报错(位置参数 -> *arg参数 -> **kwargs参数),除非必需参数在传参的时候使用了关键字参数
    5. 特殊参数:可以使用/*来限制参数的传递形式
      1. /为仅限位置参数,限制在它之前的形参必须以位置参数的形式传入,而不能用关键字参数
      2. *为仅限关键字参数,限制在它之后的形参必须以关键字参数的形式传入
      3. 这两个特殊参数只是为了限制参数的传递形式,不需要为它们传入实参
def func(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
	pass
func(1, 2, 3, kwd1=4, kwd2=5)
  1. 匿名函数
    1. 格式: lambda [arg1 [, arg2, ... argN]] : expression
  2. 封包、解包
    1. 封包:将多个值赋值给一个变量时,Python 会自动将这些值封装成元组,这个特性称之为封包
    2. 解包:可迭代对象都支持解包,解包符号为星号
      1. 赋值过程中的解包: a,*b=(1,2,3) #a=1,b=[2,3]在其中一个变量前面加星号,代表可以接收多个元素,并组成列表来赋值。注意不允许多个带星号的变量
      2. 在可迭代对象前面加一个星号(*),在字典对象前面加双星(**),这种解包方式主要运用在函数传参的过程中
      3. 可以结合 json 使用
def func(a, b, c, d=None):
	print(a, b, c, d)

# 在可迭代对象前面加一个星号(*),使其以位置参数的形式传入函数
tup = (1, 2, 3, 4)
dic = {'name': "Tom", 'age': 18, 'height': 188}
func(*tup) # 等效于 func(1, 2, 3, 4)
func(*dic) # 等效于 func('name', 'age', 'height')

# 在字典对象前面加双星(**),使其以关键字参数的形式传入函数
dic = {'a': "Tom", 'b': 18, 'c': 188, 'd': True}
func(**dic) # 等效于 func(a="Tom", b=18, c=188, d=True)

dict(**dic) # 等效于 dict(a="Tom", b=18, c=188, d=True)

#使用json传递值
import json
jsonData = """
{
    "a": "Tom",
    "b": 18,
    "c": 188,
    "d": "True"
}
"""
text = json.loads(jsonData)

func(**text)
  1. 命名空间
    1. 内置命名空间
      1. builtins 查看
      2. dir([object])返回object的属性、方法列表的字符串数组
      3. locals() globals()返回 变量名 和 变量值 的字典
    2. 全局命名空间:包含模块中定义的名称,记录了模块的变量、函数、类、其它导入的模块等,在模块被读入时创建,持续到解释器退出
    3. 局部命名空间:包含函数中定义的名称,记录了函数的变量、参数等。一个函数的局部命名空间在这个函数被调用时创建,持续到函数结束
    4. 命名空间查找顺序:局部命名空间 -> 全局命名空间 -> 内置命名空间
    5. eval(expression[, globals[, locals]])exec(object[, globals[, locals]])
      1. eval() 和 exec() 函数的功能相似,都可以执行一个字符串形式的Python 代码
      2. 区别:eval()函数只能执行单个表达式,并返回执行的结果;而exec()函数还可以执行代码块,无返回值(return None)
obj = "print(abs(-3))"
exec(obj)

obj = """
a = -3
if a < 0:
print(-a)
else:
print(a)
"""
exec(obj)
  1. 作用域
    1. 说明:只有 模块、类、函数 才会引入新的作用域
    2. 规则:在当前作用域如果找不到对应名称,则去更大一级作用域去找,直到最后找不到就会报错。 L - E - G - B 作用域依次增大
    3. 局部作用域 (Local) - L :函数、匿名函数中
    4. 闭包外的函数中 (Enclosing) - E :闭包外的函数中
    5. 全局作用域 (Global) - G
    6. 内建作用域 (Built-in) - B :在 builtins 模块中
    7. global 和 nonlocal
      1. 当内部作用域想要给外部作用域的变量重新赋值时,可以用 global 或 nonlocal 关键字
def outer():
    global a, b # 声明当前作用域的a,b为全局变量
    a, b, c, d = 3, 4, 5, 6
    print(a, b)
    def inner():
        global a, b # 声明当前作用域的a,b为全局变量
        nonlocal c, d # 声明当前作用域的c,d为Enclosing变量
        a, b, c, d = 7, 8, 9, 0
    inner()
    print(a, b)
    print(c, d)
a, b = 1, 2
outer()
print(a, b)
  1. 内置函数
  2. 常用高阶函数:参数或返回值为其他函数的函数
    1. filter(function, iterable): 将 iterable 中每个元素作为参数传递给函数,根据函数的返回结果进行判断 True 或 False,将判断为 True 的 iterable 中的元素构建新的迭代器并返回
    2. map(func,*iterables): 用 iterables 中的每个元素作为函数的参数来调用函数,以迭代器形式返回所有结果。当有多个 iterables 对象时,最短的 iterables 耗尽则函数停止
    3. reduce(function, iterable[, initial]):在指定 initial 参数时,先把 initial 值和 iterable 的第一个元素作为参数调用函数,把这次函数的结果以及 iterable 的下一个元素又作为参数再调用函数,以此类推
from functools import reduce
def add(m, n):
    s = m + n
    print(s)
    return s # 如果改为 print(s) 会怎样?

# 过程:[(1+2)+3]+4 = 10
result = reduce(add, [1, 2, 3, 4])
print(result)

'''
3
6
10
10
'''

闭包 和 装饰器

  1. 闭包:
    1. 在函数嵌套(函数里面再定义函数)的前提下
    2. 内部函数使用了外部函数的变量(参数)
    3. 外部函数的返回值是内部函数的引用
    4. 一般来说,如果一个函数结束,函数内部的变量、参数会被释放掉;而闭包则不同,它在外部函数结束时,会把内部函数中用到的外部函数的变量、参数保存到内部函数的__closure__属性中,以提供给内部函数使用
  2. 装饰器:顾名思义就是起装饰作用的,不改变原来函数作用的,只是在原来函数上增加些额外的功能
  3. 多层装饰器,查看执行顺序
#多层装饰器

import time

def deco(func):
  print("in wrapper1")
  #闭包函数
  def wrapper1(*args):
    print("start wrapper1")
    res = func(*args)
    print("end wrapper1")
    return res
  print("out wrapper1")
  return wrapper1

def timer(func):
  print("in wrapper2")
  def wrapper2(*args):
    print("start wrapper2")
    start_time = time.time()
    res = func(*args)
    end_time = time.time()
    print("函数耗时:{}".format(end_time-start_time))
    print("end wrapper2")
    return res
  print("out wrapper2")
  return wrapper2

@deco
@timer
def add(*args):
  print("start add")
  time.sleep(2)
  print("end add")
  return sum(args)

print(add(3, 4, 5))

#add其实是变化的函数的主体,deco和timer定义了这个变化函数周围固定的上下文作用,
#比如画不同的圆、方块、其他图形,可能载入的上下文都一样,就这个绘制部分的函数不一样,则可以使用装饰器
in wrapper2
out wrapper2
in wrapper1
out wrapper1
start wrapper1
start wrapper2
start add
end add
函数耗时:2.0025978088378906
end wrapper2
end wrapper1
12
  1. 类中特殊的装饰器
class Student:
  def __init__(self, name, age):
    self.name = name
    self.age = age

  @property
  def adult_age_p(self):
    return 18

  def adult_age(self):
    return 18

  @staticmethod
  def adult_age_static(): #静态函数参数中不添加self
    return 30

  @classmethod
  def adult_age_class(cls,param): #class函数中注意添加cls参数
    return param

  @property
  def adult_flag(self):
    return self.age >= self.adult_age_p

stu = Student("张三", 18)
print(stu.adult_age()) # 没有加@property, 必须使用正常的调用方法的形式, 在后面加()
print(stu.adult_age_p) # 加了@property, 用调用属性的形式来调用方法, 后面不需要加()
print(stu.adult_flag) # True
print(Student.adult_age_static())
#print(Student.adult_age()) 不是静态函数不可直接使用
print(Student.adult_age_class(29))
stu.age = 17 # 可以修改stu对象的age属性
# stu.adult_age_p = 19 # 报错:@property将方法装饰为只读属性, 不能修改
print(stu.adult_flag) # False
18
18
True
30
29
False

魔法方法

Python常用魔术方法
定义:类中的魔术方法是官方定义好的,以两个下划线开头且以两个下划线结尾来命名的方法。在特定情况下,它会被自动调用,不需要我们主动调用该方法。

  1. init(self[,…]) : 构造函数
  2. call(self[,…]) :当实例对象像函数那样被“调用”时,会调用该方法
#__init__和__call__区别
class test:
    def __init__(self):
        print('__init__')
    def __call__(self):
        print('__call__')
test()
a = test()
a()

'''
__init__
__init__
__call__
'''
  1. getitem(self,key) : 当执行 self[key] 操作时,会调用该方法
  2. len(self) : 对实例对象求长度len()时,会调用该方法,要求必需返回整数类型
class Ex:
    def __getitem__(self, key):
        print(f"__getitem__被调用, key: {key}")
        print(["a", "b", "c"][key])
        print({0: "零", 1: "壹", 2: "贰"}[key])

    def __len__(self):
        return 1234
e = Ex()
e[2]
print(len(e))
'''
__getitem__被调用, key: 2
c
贰
1234
'''
  1. _repr(self) / str(self) : 实例对象转字符串时,会调用该方法,要求必需返回字符串类型
    1. __repr__正式,str 非正式。
    2. __str__主要由 str(),format()和print()三个方法调用。__repr__由repr()调用
    3. 若定义了__repr__没有定义__str__,那么本该由__str__展示的字符串会由__repr__代替。
    4. __repr__主要用于调试和开发,而__str__用于为最终用户创建输出。
    5. 可以看出repr()更能显示出对象的类型、值等信息,对象描述清晰的。 而str()能够让我们最快速了解到对象的内容,可读性较高。
import datetime
s = 'hello'
d = datetime.datetime.now()
print(str(s))
print(repr(s))
print(str(d))
print(repr(d))

'''
hello
'hello'
2018-11-29 22:39:18.014587
datetime.datetime(2018, 11, 29, 22, 39, 18, 14587)
'''
  1. 运算符重载:
    1. add(self, other), radd(self, other):add为self+other, radd为other+self,以下同,每个运算操作符有左右两个,可能为了有矩阵这样的
    2. sub(self, other), rsub(self, other)
    3. mul(self, other), rmul(self, other)
    4. truediv(self, other), rtruediv(self, other)
    5. neg(self, other)

文件读写

  1. open(file, mode='r', encoding=None)
    1. file:文件路径(相对路径或绝对路径)
    2. mode:文件打开的模式,默认为 ‘r’ 模式,常用r(只读),w(写入),x(只创),a(追加),+(读写),b(二进制)
    3. encoding:编码方式(只用在文本模式下),默认依赖平台,通常设置为 ‘UTF-8’
    4. 打开 file 对应的文件,返回一个文件对象;如果该文件不能被打开,则引发 OSError
  2. with 语句
    1. 常用open写法有一个潜在问题,如果在调用 write 的过程中出现了异常,则会导致 close 方法无法被正常调用,导致资源占用的浪费。
    2. with 语句 会自动创建__enter__ __exit__,在结束 with 语句体后会自动close文件
with open(r'./t01.txt', mode='w') as file:
	file.write('hello world')
  1. json 读写
import json
info = {'name': 'Tom', 'age': 18, 1: 'one'}
print(type(info), info)

with open("info.json", mode="w") as f:
    info_str = json.dumps(info) # 序列化
    print(type(info_str), info_str)
    f.write(info_str)
    
with open("info.json") as f:
    content = f.read()
    print(type(content), content)
    res = json.loads(content) # 反序列化
    print(type(res), res)

模块、包

  1. 模块
    1. 模块是一个包含Python定义和语句的文件,文件名就是模块名后跟文件后缀 .py
    2. 一个模块被另一个程序导入时,会执行该模块
    3. 一个模块只会被另一个程序导入一次
    4. __name__属性:
      1. 每个模块都有一个__name__属性,当其值是 ‘main’ 时,说明该模块自身在运行,否则说明该模块被导入,其值为模块名
      2. 在完成一个模块的编写之前,我们一般会对模块中的功能进行测试,看看各项功能是否正常运行。对于这些测试的代码,我们希望只在直接运行这个py文件的时候执行,而在用其他的程序导入这个模块的时候不要执行。这个时候就可以借助__name__属性来实现
print('在该模块自身运行时会执行')
print('在该模块被导入时也会执行')

if __name__ == '__main__':
	print('在if语句下的程序块仅在该模块自身运行时才执行')
else:
	print('在else子句下的程序块在该模块自身运行时不会执行')
	print('但是在被导入时, 会执行')
    1. Python包实际上就是一个文件夹,只是该文件夹里面一定包含__init__.py 模块。和文件夹一样,包里面还可以装其他的包
    2. 避免相同命名冲突: 如果在同一个包里,是不允许两个模块命名相同的,但是如果不在同一个包里,是可以的
    3. 模块分区: 把不同功能的模块归类到不同的包里,方便查询和修改。在比较大型的项目中常常需要编写大量的模块,此时我们可以使用包来对这些模块进行管理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值