Python学习心得

本文涵盖了Python编程的多个关键概念,包括模块、切片、迭代、列表生成式、生成器、迭代器、函数式编程、高阶函数、闭包、匿名函数、可变参数、关键字参数等。介绍了如何使用模块中的作用域、切片操作、迭代方式,以及如何创建和使用生成器。还深入探讨了函数式编程,如高阶函数和装饰器,并讲解了如何处理可变参数和关键字参数。此外,文章还涉及到了浅拷贝和深拷贝的区别,多进程和线程的运用,文件读写,集合操作,以及正则表达式的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

模块

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

' a test module '

__author__ = 'Lorenz Xu'

import sys

def test():
    args = sys.argv
    if len(args)==1:
        print('Hello, world!')
    elif len(args)==2:
        print('Hello, %s!' % args[1])
    else:
        print('Too many arguments!')

if __name__=='__main__':
    test()

第1行注释可以让这个hello.py文件直接在Unix/Linux/Mac上运行
第2行注释表示.py文件本身使用标准UTF-8编码
第4行是一个字符串,表示模块的文档注释,任何模块代码的第一个字符串都被视为模块的文档注释
第6行使用__author__变量把作者写进去,这样当你公开源代码后别人就可以瞻仰你的大名
最后一行,使用命令行运行hello.py时,__name__被解析为__main__,所以会执行最后一行,但是在Python交互环境需要先输入hello.test()

模块中的作用域

类似_xxx__xxx这样的函数或变量就是非公开的(private)

切片

>>> L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']
>>> L[0:3]
['Michael', 'Sarah', 'Tracy']
>>> L[1:3]
['Sarah', 'Tracy']

倒数切片

>>> L[-2:]
['Bob', 'Jack']
>>> L[-2:-1]
['Bob']

隔项切片

>>> L[:10:2]
[0, 2, 4, 6, 8]

元祖tuple切片

>>> 'ABCDEFG'[:3]
'ABC'
>>> 'ABCDEFG'[::2]
'ACEG'

迭代

>>> d = {'a': 1, 'b': 2, 'c': 3}
>>> for key in d:
...     print(key)
...
a
c
b

for value in d.values()值迭代
for k, v in d.items()键值同时迭代

通过collections模块的Iterable类型判断是否可以迭代

>>> from collections import Iterable
>>> isinstance('abc', Iterable) # str是否可迭代
True
>>> isinstance([1,2,3], Iterable) # list是否可迭代
True
>>> isinstance(123, Iterable) # 整数是否可迭代
False

Python内置的enumerate函数可以把一个list变成索引-元素对,同时迭代索引和值

>>> for i, value in enumerate(['A', 'B', 'C']):
...     print(i, value)
...
0 A
1 B
2 C

列表生成式

普通形式
>>> list(range(1, 11))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
两层循环
>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
还能加上判断
>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]

生成器

把列表生成式的[]改成()就是生成器
>>> g = (x * x for x in range(10))
>>> for n in g:
...     print(n)
... 
0
1
4
9
16
25
36
49
64
81

定义generator的另一种方法。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator

迭代函数
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'


>>> f = fib(6)
>>> f
<generator object fib at 0x104feaaa0>

函数形式生成器第一次遇到yield返回,第二次遇到继续执行

迭代器

Iterator对象表示的是一个数据流,可以被next()函数调用并不断返回下一个值,直到没有数据时抛出StopIteration错误的对象称为迭代器:Iterator
可以使用isinstance()判断一个对象是否是Iterable对象:

>>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False

使用isinstance()判断一个对象是否是Iterator对象:

>>> from collections import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('abc', Iterator)
False

listdictstr虽然是Iterable,却不是Iterator

listdictstrIterable变成Iterator可以使用iter()函数

>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True

函数式编程

就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。
函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!

高阶函数

一个函数接收另一个函数作为参数,这种函数就称之为高阶函数。
map()函数接收两个参数,一个是函数,一个是Iterable

>>> def f(x):
...     return x * x
...
>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
['1', '2', '3', '4', '5', '6', '7', '8', '9']

reduc())把结果继续和序列的下一个元素做累积计算
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
内建的filter()函数用于过滤序列。

def not_empty(s):
    return s and s.strip()

list(filter(not_empty, ['A', '', 'B', None, 'C', '  ']))
# 结果: ['A', 'B', 'C']

内置的sorted()函数就可以对list进行排序,sort()也是高阶函数

>>> sorted([36, 5, -12, 9, -21], key=abs)
[5, 9, -12, -21, 36]

对字符串排序,是按照ASCII的大小比较的,由于’Z’ < ‘a’,结果,大写字母Z会排在小写字母a的前面。

闭包

def count():
    fs = []
    for i in range(1, 4):
        def f():
             return i*i
        fs.append(f)
    return fs

f1, f2, f3 = count()


>>> f1()
9
>>> f2()
9
>>> f3()
9

返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

匿名函数

关键字lambda表示匿名函数,冒号前面的x表示函数参数。
匿名函数lambda x: x * x实际上就是:

def f(x):
    return x * x

L[]也是一个变量

def add_end(L=[]):
    L.append('END')
    return L


>>> add_end()
['END', 'END']
>>> add_end()
['END', 'END', 'END']

改法如下:

def add_end(L=None):
    if L is None:
        L = []
    L.append('END')
    return L


>>> add_end()
['END']
>>> add_end()
['END']

可变参数

一般来说,传入函数的参数数量是根据函数签名来决定的,是不变的,
但是
可以Python可以传list或tuple,相当于传了一个参数,
还可以
在参数前加一个*变成元组(Tuple)。

def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum

>>> calc(1, 2)
5
>>> calc()
0

关键字参数

两个**把参数变为字典(dict)。

def person(name, age, **kw):
    print('name:', name, 'age:', age, 'other:', kw)

>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}

命名关键字参数

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('Jack', 24, city='Beijing', job='Engineer')
Jack 24 Beijing Engineer

参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。

装饰器

def log(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

@log
def now():
    print('2015-3-25')

>>> now()
call now():
2015-3-25

其中@log等价于now = log(now)
还需要使用@functools.wraps(func)不然now.__name__会变成'wrapper'

import functools

def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

偏函数

functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。

>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85

浅拷贝深拷贝

a=[1,2,3]
a=b
那么a改变b也会改变

使用copy里面的copy方法
b = copy.copy(a)
但是a=[1,2,[3,4]]
改变a里面的list,b里面的list也会改变,外面的list不会改变

使用b = copy.deepcopy(a)
能真正够达到a改变,b会变得效果

多进程Multiprocessing

与线程的操作方式类似

import multiprocessing as mp

def job(q):
    for res in range(100):
        res+=1
    q.put(res)


if __name__ == "__main__":
    q = mp.Queue()
    p1 =mp.Process(target = job,args=(q,))
    p1.start()
    p1.join()
    print(q.get())

进程池

import multiprocessing as mp

def job(q):
    return q*q

if __name__ == "__main__":
    pool = mp.Pool(processes=4)
    res = pool.map(job,range(10))
    print(res)
    #使用apply_async(),只能计算一个值,返回一个对象,要返回结果只能用get()
    res = pool.apply_async(job,(2,))
    print(res.get())
    #使用迭代器,可以计算多个值
    res = [pool.apply_async(job,(i,)) for i in range(10)]
    print([xty.get() for xty in res])

进程中不能定义全局变量,要使用共享内存,如下定义

var = mp.Value("d",100)
array = mp.Array("i",[1,3,4])

进程lock锁,是进程间互不干扰

import multiprocessing as mp

def job(v,num,l):
    l.acquire()
    for i in range(10):
        v.value += num
        print(v.value)
    l.release()
if __name__ =="__main__":
    l = mp.Lock()
    v = mp.Value("I",0)
    p1 = mp.Process(target=job,args=(v,1,l))
    p2 = mp.Process(target=job,args = (v,3,l))
    p1.start()
    p2.start()

线程相关的方法,操作

import threading

def main():
#有几个激活的threading
    print(threading.active_count())
#列举激活的threading名字
    print(threading.enumerate())
#正在运行的线程
    print(threading.current_thread())
if __name__=="__main__":
    main()

添加线程以及参与工作

import threading

def thread_job():
    print("add thread,and thread name is %s"%threading.current_thread())

def main():
    add_thread = threading.Thread(target = thread_job)
    add_thread.start()
if __name__=="__main__":
    main()

join()方法,可以使线程等待另一线程

线程的lock

import threading
import time
from queue import Queue


def job1():
    global a,lock
    lock.acquire()
    for i in range(10):
        a+=1
        print("job1",a)
    lock.release()

def job2():
    global a,lock
    lock.acquire()
    for i in range(10):
        a+=10
        print("job2",a)
    lock.release()


if __name__ =="__main__":
    lock = threading.Lock()
    a = 0
    t1 = threading.Thread(target=job1)
    t2 = threading.Thread(target=job2)
    t1.start()
    t2.start()

读写文件

此处创建一个叫xty.pickle的文件夹,dump把a_dict里面的内容写进文件夹中

import pickle
a_dict = {"da":111,2:[12,31]}
file = open("xty.pickle","wb")
pickle.dump(a_dict,file)

把已生成的文件夹xty.pickle里面的内容load进a_dict2中

import pickle
a_dict = {"da":111,2:[12,31]}
with open("xty.pickle","rb") as file:
    a_dict1 = pickle.load(file)
    print(a_dict1)

set()可以去除list中的相同项

list = ["a","a","b","c","f",1,2,4,1,4,1]
print(set(list))
生成一个set集合,但不是字典
{1, 2, 4, 'a', 'f', 'b', 'c'}

可以结合add(),增加元素
clear(),清除,返回set()
remove(),去除一个元素,当去除的元素本来就没有时报错
discard(),效果与上面的remove()一样,但是不会报错
找出set1中set2也不纯在的元素

list = {"a","a","b","c","f"}
set2 = {"a","e","f"}
print(list.difference(set2)),找出set1中set2也不纯在的元素

寻找两个字典中相同的项

print(list.intersection(set2))

正则表达式(Regular Expression RegEx)

search查找是否有相同的

import re
pa1 = "cat"
pa2 = "dog"
string = "dog and xty"
print(re.search(pa1,string))

r"x[a-z0-9]y",在正则表达式前加r,[]中的内容表示可选
\d表示全部数字
\D表示全部字母
\s表示全部空白符
\S匹配不是空白符的东西
\w表示[a-zA-Z0-9_]
\W表示除了\w以外的都可以匹配
\匹配反斜杠
.匹配空行以外的东西
^匹配句首的,加flags = re.M使段落每一行都可以匹配
$匹配句尾的
+匹配一次或多次
*匹配零次或多次
{}可自己定匹配次数
group()选择组的第几个匹配
?P<id>给组加id
findall返回能匹配的所有东西
sub()替换,re.sub(pa1,"fw",string)

split()分裂,
string = "dog ;and/ xty"
print(re.split(r"[,.;/]" ,string))
[]内代表的是需要被分裂的符号,空格是默认的

compile(),把正则表达式先储存在一个变量中,

compile_re = re.compile(r"[ua]n")
print(compile_re.search(string))

。。。
。。。

import re
pa1 = r"x[a-z0-9]y"
string = "dog and xty"
print(re.search(pa1,string))

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值