抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

再探Python:再次学习以补充知识。这次学习聚焦于巩固Python基础,填补之前的知识空白。

字符串的转义问题

字符串中的转义问题

c = 'C:\windows\nt'
c = 'C:\\windows\\nt'

更简单的方式,r前缀将字符串不要转义了

c = r'C:\windows\nt'

前缀r,把里面的所有字符当普通字符对待,则转义字符就不用转义了

a = 'abc'
b = 123
c = f'{a}********{b}'
c
'abc********123'

这里说明一下f 是用来构造字符串的。

方便字典value的引入到字符串

"My name is %(name)s, I'm %(age)d" % {'age':20, 'name': 'Jerry'}

format方式

"{}". format ((1,22))
"{0[1} --- {0[0]}".format((1,22)) # 两次引用

布尔值

False等价布尔值,相当于bool(value)

test = [] 
bool(test)
# 返回False

字符串的类型比较

type(1) == int # 注意不能是'int' 这样'int'表示为字符串
# 返回True
type(list), type(str) ,type(type)
(type,type,type) # type # type 是元类

type(True) == bool
True
isinstance(1, int)
True
isinstance(1, str)
False
isinstance(True, bool)
True
isinstance(1,(str, list, tuple, int)) ## 其中有一个符合返回True
True

input 输入

x = input('>>>') ## 阻塞输入,返回一个字符串
>>>
print(x)
123

print分隔符

print(1, 2, 3, [], [1,2,3],sep='\t\t')
print(1, 2, 3, sep='#',end='\t') # 间隔使用 # 最后使用\t

math 天花板地板

print (math. ceil (1.0), math.ceil (1.3), math.ceil (1.5), math.ceil (1.6), math.ceil (1.8))
1 2 2 2 2
print (math.floor (1.0), math. floor (1.3), math. floor (1.5), math. floor (1.8), math. floor (2.0))
1 1 1 1 2
math.ceil (-1.0), math.ceil (-1.3), math.ceil (-1.5), math.ceil (-1.6), math.ceil (-1.8)
(-1, -1, -1, -1, -1)
math.floor (-1.0), math. floor (-1.3), math. floor (-1.5), math. floor (-1.8), math. floor (-2. 9)
(-1, -2 ,-2 ,-2 ,-2 )

int()只截取整数部分
round() 找0.5最近的偶数,(四舍六入、0.5取偶)

数据库连接与建表

import pymysql

# 创建数据库连接
conn = pymysql.connect(host='localhost', user='root', password='password', database='mydb')

# 创建游标对象
cursor = conn.cursor()

# 查询表是否存在
cursor.execute("SHOW TABLES LIKE 'k8s_memory_7d_use'")
result = cursor.fetchone()

# 如果表不存在,则创建表
if not result:
    cursor.execute("""
        CREATE TABLE k8s_memory_7d_use (
            id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
            k8s_cluster VARCHAR(50) NOT NULL,
            namespace VARCHAR(50) NOT NULL,
            pod VARCHAR(50) NOT NULL,
            instance VARCHAR(50) NOT NULL,
            memory_7d_arrive_now_max_unit_M INT(11) NOT NULL,
            Memory_Limit_M INT(11) NOT NULL,
            Memory_Use_percentage FLOAT(6,2) NOT NULL
        )
    """)
    print("Table k8s_memory_7d_use created successfully")

# 关闭游标和连接
cursor.close()
conn.close()

9 * 9 乘法表练习补充

python 9*9 乘法表三元表达式实现判断格式化输出

for i in range(1,10):
    for j in range(1,i+1):
        print('{} * {} = {}'.format(j,i,i*j),end=' ')
    print()
再次优化 
for i in range(1,10):
    for j in range(1, i+1):
        print("{} * {} = {}".format(j, i, i*j), end=" " if j != i else "\n")
再次优化
for i in range(1,10):
    for j in range(1, i+1):
        print("{} * {} = {:<{}}".format(j, i, i*j, 2 if j == 1 else 3) ,end="" if j != i else "\n")
  • 前置空格方法打印棱形
n = 7
leadingchar = ' '
char = '*'
for i in range (-3, 4):
    spaces = -i if i < 0 else i
    print (spaces * leadingchar, end='') #不要検行,接着打印*
    print ( (7 - 2 * spaces) * char)
# 再次优化,使用对称方法
n = 11
e = n // 2 # 5
leadingchar = ' '
char = '*'

for i in range(-e,n-e): # e + 1
    print("{:^{}}".format((n - 2 * abs(i)) * char ,n))
  • 打印闪电
n = 13
e = n // 2
f = e + 1
for i in range (-e, f):
    if i < 0:
        print(' ' * -i + (f+i) * '*')
    elif i > 0:
        print(' ' * e + (f - i ) * '*')
    else: # > 0
        print (n * '*')
  • 求斐波那契数列第101项
a = 1
b = 1
print('index={}, fib={}'.format(0, 0))
print('index={}, fib={}'.format(1,a))
print('index={}, fib={}'.format(2,b))
index = 2

while True:
    c = a + b 
    index += 1
    print('index={}, fib={}'.format(index, c))
    if index == 101: break
    a = b
    b = c
  • 10000以内的素数
import datetime

start = datetime.datetime.now()

count = 1  # 2 偶数, 质数 

# 偶数 

for x in range(3,100000,2): # 只测试奇数,减少一半的计算量
    for i in range(3, int(x ** 0.5) +1 ,2): #[2, "中点"], 奇数不需和2取模
        if x % i == 0: # 被整除,说明是合数
            break # 只要途中被任何一个数整除,就不是质数,跳出循环
    else: # 循环正常结束,说明是质数
        #print(x)
        count += 1
delta = (datetime.datetime.now() - start).total_seconds()
print('count={}, time={}'.format(count, delta))

# 算法优化

import datetime

n = 100000

start = datetime.datetime.now()

count = 2 # 隐含着2和3 

primenumbers = [3] # 下面代码要求列表中至少得有一个质数,为什么是3 ?

for i in range(5,n,2): # 从5开始,每次加2,因为偶数肯定不是质数,所以不用判断 ,所以舍弃所有偶数
    edge = int(i ** 0.5) + 1 # 为什么要加1 ?,因为range函数不包含最后一个数 
    flag = False # 不是质数

    for j in primenumbers:
        if j > edge: # 为什么要判断j > edge ?,因为如果j > edge,那么i肯定不是质数,所以可以跳出循环
            break
        if i % j == 0:
            flag = True # 是质数
            break
    if not flag:
        primenumbers.append(i) # 将质数添加到列表中
        count += 1
delta = (datetime.datetime.now() - start).total_seconds()
print(delta)
print(count)

## 孪生素数

import datetime

start = datetime.datetime.now()

n = 1000000
x =7 
step = 4
primenumbers = [3,5] # 
count = 3 

while x < n:
    if x % 5 != 0: # 为什么要判断x % 5 != 0 ?,因为5的倍数肯定不是孪生素数,所以可以跳过
        edge = int(x ** 0.5) + 1 # 为什么要加1 ?,因为range函数不包含最后一个数
        flag = False # 不是孪生素数
        for i in primenumbers: # 为什么要遍历质数列表 ?,因为如果x是质数,那么x-2和x+2也是质数,所以可以跳过
            if i > edge:
                flag = True # 是孪生素数
                break
            if x % i == 0:
                break # 合数
        if  flag: # 如果是孪生素数,就添加到列表中
            primenumbers.append(x)
            count += 1
    x += step
    step = 4 if step == 2 else 2 # 为什么要这样写 ?,因为x+2和x+4都是偶数,所以可以跳过
delta = (datetime.datetime.now() - start).total_seconds()
print(delta,count)
  • python 变量调用计数获取
# 列表
x = [] # 新建的空列表

import sys
sys.getrefcount(x)

记录vue element-plus 错误处理

vue WEBPACK_IMPORTED_MODULE is not a function 报错处理

npm update vue

bytes生成字母表

bytes(range(65, 91))
b'ABCDEFGHIJKLMNOPORSTUVWXYZ'
bytes(range(65+0x20, 91+32))
b'abcdefghijklmnopqrstuvwxyz'

切片补充

In [5]: aa = [0,1,2,3,4,5,6,7,8,9]
# 列表倒序
In [6]: aa[::-1]
Out[6]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
# 列表步长为2的跨度
In [7]: aa[::2]
Out[7]: [0, 2, 4, 6, 8]
# 列表步长为2的跨度倒序
In [8]: aa[::-2]
Out[8]: [9, 7, 5, 3, 1]
# 替换迭代对象,切片并赋值
In [9]: t = [10, 50, 2, 3, 4]
In [10]: t[1:] = range(10,20)
In [11]: t
Out[11]: [10, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

补充es

# 查看失败的报错
GET     /_cluster/allocation/explain 
# 查看报错中的提示
POST /_cluster/reroute?retry_failed=true
# 查看恢复情况
GET /_cat/allocation?v
# 解析式,推导式
[i for i in range(5)]
[list(range(5))]
[*range(5)] # python3.5 之后的新的用法
列表是可迭代对象,生成器也是可迭代对象;
生成器也是迭代器一种,但列表不是;
迭代器特点:
1. 一次性迭代,指针不会回头 
2. 类似range(range不是迭代器),是惰性,但next可以挤一下
3. for循环可以迭代,但是如果已经到头,for相当于迭代空容器但是next 不能迭代,如果使用next会抛出 StopIteration
[str(i) for i in range(5)]
[list(map(str,range[5]))]
  • 生成器表达式和列表解析式对比
    • 计算方式
      • 生成器表达式延迟计算,列表解析式立即计算
    • 内存占用
      • 单从返回值本身来说,生成吕表达式省内存,列表解析式返回新的列表;
      • 生成器没有数据,内存占用极少,但用的时候,一次返回一个数据,只会战胜一个数据的空间;
      • 列表解析式构造新的列表需要为所有元素立即占用掉内存;
    • 计算速度
      • 单看计算时间看,生成器表达式耗时非常短,列表解析式耗时长;
      • 但生成器本身并没有返回任何值,只返回了一个生成器对象;
      • 列表解析式构造并返回了一个新的列表。
sorted(dict(a=1, b='123',c=200).values(),key=str)
# str(1) > str('123')
# '1' '123' '299' 转换完的结果只是用来排座次,不影响输出
# def 关键字,define定义,定义时
def add(x, y) # add标识符,函数名,指向一个函数对象;
#(参数列表),参数列表中呆以有n个参数(可以是0个),这些参数叫做形式参数,简称形参。形参也是标识符
    result = x +y # 函数逻辑
    return result # return返回值
ret = add(4, 5) #函数标识符后面加(),就是调用,执行called。调用时
print(ret)
In [2]: import string

In [3]: print(string.ascii_lowercase)
abcdefghijklmnopqrstuvwxyz

In [4]: alphabet = 'abcdefghijklmnopqrstuvwxyz'

In [5]: alphabet= "".join(chr(i) for i in range(0x61, 0x61+26))

In [6]: alphabet
Out[6]: 'abcdefghijklmnopqrstuvwxyz'
In [14]: for i in range(1,10):
    ...:     id = "{:0>6}.{}".format(i, '')
    ...:     print(id)
    ...: 
000001.
000002.
000003.
000004.
000005.
000006.
000007.
000008.
000009.
def config(host,port, **kwargs)
    print(host) # 作为配置的函数 地址和端口必须传进来
    print(port) #
    print(kwargs)
config('localhost', 3306,username='test')
  • 形参
    • 可以有缺省值、定义时,如果没有提供该参数,动用缺省值。缺省值的定义往后放;
    • 5种
    • 1普通形参: 可以有缺省值,2种传实参的方式都可以用
    • 2*args 可变仅位置形参,只能接收按照位置传入的实参,可以接收0个或任意个。没有缺省值;
    • 3**kwargs可变仅关键字形参,只能接收关键字传入的实参,可以接收0个或任意个。形参的最后一个,没有缺省值。
# 思考
def fn(x,y=5,*args,**kwargs):
    print(x,y,args,**kwargs)
fn(1),fn(x=5),fn(x=6,y=7),fn(a=7,x=10),

运维常用函数定义方法

def config(host,username='renjin',password='renjin', *, port=3306, **options):
    db = options.get('db','test')
    connstr = "mysql://{}:{}@{}:{}/{}?charset=utf8".format(username,password,host,port,db)
    print(connstr)


config('www.asjin.com','root','testpwd',port=3397,db='cmdb')
#  python3 rjtest1.py
mysql://root:testpwd@www.asjin.com:3397/cmdb?charset=utf8
  • def config(...): - 这是一个函数定义的开始,函数名为config,后面的括号内包含函数的参数。
  • host - 这是函数的第一个参数,表示要连接到的MySQL数据库的主机名或IP地址。
  • username='renjin' - 这是一个可选的参数,默认值为’renjin’。它表示连接数据库时要使用的用户名。如果不提供该参数,将使用默认值’renjin’。
  • password='renjin' - 这是另一个可选的参数,默认值也为’renjin’。它表示连接数据库时要使用的密码。如果不提供该参数,将使用默认值’renjin’。
  • *, port=3306 - 这里的星号(*)表示从这里开始,后面的参数必须以关键字参数的方式传递,不能使用位置参数。port 是一个关键字参数,它表示要连接的MySQL数据库的端口号,默认为3306。如果提供了端口号,它将覆盖默认值。
  • **options - 这是一个特殊的语法,表示接受任意数量的关键字参数,并将它们存储在一个名为options的字典中。这些参数可以用于传递一些其他的配置选项,如数据库名称等。

参数解构

* 对容器解构,按照位置传实参,字典取的是key
** 只用于mapping,按照kv对实现关键字的传参,key要和形参对应起来

'''参数解构'''

def add(*nums):
    s = 0 
    for i in nums:
        s += i
    return s

print(add(*[1,2]),add(*(1,2)),add(*{1,2}),add(*{'a':1,'b':2}.values()))

'''打印结果是'''
# 3 3 3 3

def x(a,b):
    return a + b
print(x(**{'a':100,'b':200}))

'''打印结果是'''
# 300

一般情况下,python函数遇到return时,将不再执行剩下的语句,而立即返回;

引用函数并解构

def fn():
    return 1, 3, 5

x, y, z = fn()
# 这时x的值为1

作用域: 标识符的可见范围
函数开辟了一个作用域,x被限制在了函数作用域中,对外不可见;
全局的、函数外的变量、对内穿透;全局变量、即全局可见;
全局变量也是有作用域的,只不过是全局变量、因此全局可见;
反过来,局部变量、即内部变量、只能在内部看到;

函数可以嵌套

简单的示例

'''打印结果是'''

def outer():
    o = 65 
    def inner():
        print('in inner',o,chr(o))
    inner()
    print('in outer',o,chr(o))

outer()
'''打印结果是'''    
# in inner 65 A
# in outer 65 A

那么以下示例的结果分析呢 ?

def outer1():
    o = 65
    def inner():
        o = 97
        print('in inner',o,chr(o))
    inner()
    print('in outer',o,chr(o))
'''打印结果是'''
# in inner 97 a
# in outer 65 A

全局变量与局部变量的坑点

'''局部变量报错测试'''
z = 100
def fn3():
    print(z)
    m = z + 1
    print(m)
    z = z + 1
    print(z)
fn3()
# 报错
# UnboundLocalError: local variable 'z' referenced before assignment
# 原因是z = z + 1中的z是局部变量,而print(z)中的z是全局变量,所以报错,只要函数中出现了 z=xxx 的赋值语句,z就是局部变量,不管有没有执行到,都是局部变量,所以在print(z)中就会报错,解决办法是在函数中加上global z,表示z是全局变量,不是局部变量,这样就不会报错了。

这样就可以穿透进来

z = 100
def fn2():
    print(z)
    t = z + 1
    print(t)
fn2()
# 打印结果是
# 100
# 101
  • 在函数中 global z 声明z不再是局部变量,而是全局变量;
  • 全局变量,如果所有函数都是用的全局变量,但是局部作用域就没有用了,全局变量污染了。
  • 全局变量也是有作用域的,只不过是全局的,所以全局可见;
  • 全局变量一般都是公用的,一般情况下不要修改;
  • 函数中形参一定是局部变量
  • 函数使用全局变量,一定要使用传参,而不是使用穿透;

Faas Sass Iaas Pass

闭包

def inc():
    c = [0] # 自由变量
    def inner():
        c[0] += 1
        return c[0]
    return inner

foo = inc() # foo ? , 
print(1,foo())
print(2,foo())

# 函数执行原理:
# 每一次函数执行都是独立的
# 函数调用完成以后局部变量消亡
# 标识符给程序员用,但是CPU不用CPU只认地址

函数的销毁

  • 定义一个函数就是生成一个函数的对象,函数名指向的就是函数对象;
  • 可以使用del语句删除函数,使其引用计数减1;
  • 可以使用同名标识符覆盖原有定义,本质上也是使用其引用计数减1;
  • Python程序结束时,所有对象销毁;
  • 函数也是对象,也不例外,是否销毁,还是看引用计数是否减为0;

变量名解析原则LEGB*

  • local,本地作用域、局部作用域的local命名空间。函数调用时创建,调用结束消亡;
  • Enclosing, Python2.2时引入了嵌套函数,实现了闭包,这个就是嵌套函数的外部函数的命名空间;
  • Global,全局作用域名,即一个模块的命名空间。模块被import时创建,解释器退出时消亡;
  • build-in,内置模块的命名空间,生命周期从python解释器容器启动时创建到解释器退出时消亡。例如print(open),print和open都是内置的变量;

匿名函数

(lambda *args: [i+1 for i in args])(*range(10))
# 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
(lambda *args: {i%3 for i in args})(*range(10))
# 输出 {0, 1, 2}
dict(map(lambda x: (x,x**2),range(10)))
# 输出 {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

",".join(map(str,range(10)))
# 输出 '0,1,2,3,4,5,6,7,8,9'

{str(i):i+1 for i in range(10)}
# {'0': 1, '1': 2, '2': 3, '3': 4, '4': 5, '5': 6, '6': 7, '7': 8, '8': 9, '9': 10}

需求 我要一个字典,kv对,key对应的value必须是列表

d1 =  {k:[] for k in 'abcde'}
print(d1)
d1['a'].append(1)
print(d1)
# 改变一个key 对应的Value指定的Key对应的value发生了改变

d1 = dict(map(lambda x: (x,[]),'abcde'))
print(d1)
d1['a'].append(1)
print(d1)
# 改变一个key 对应的Value指定的Key对应的value发生了改变

d1 = dict.fromkeys('abcde',[])
print(d1)
d1['a'].append(1)
print(d1)
# 改变一个key 对应的value都发生了改变
# 输出结果 {'a': [], 'b': [], 'c': [], 'd': [], 'e': []}
# 输出结果 {'a': [1], 'b': [1], 'c': [1], 'd': [1], 'e': [1]}
# 因此这种方法使用时要注意
from collections import defaultdict
d2 = defaultdict(lambda: {100})
print(d2['m'])
print(d2)

# 输出结果
# {100}
# defaultdict(<function <lambda> at 0x7f8f1c0b2d90>, {'m': {100}})

In [1]: (lambda *args: [i+1 for i in args])(*range(5))
Out[1]: [1, 2, 3, 4, 5]

In [2]: (lambda *args: list((i+1 for i in args)))(*range(5))
Out[2]: [1, 2, 3, 4, 5]

In [3]: dict(map(lambda x:(str(x), x+1), range(5)))
Out[3]: {'0': 1, '1': 2, '2': 3, '3': 4, '4': 5}

比如正常代码中的一些需求、需一个字典、kv对,key对应的value必须是列表

In [4]: d1 = dict(map(lambda x: (x,[]), 'abcde'))
In [5]: d1
Out[5]: {'a': [], 'b': [], 'c': [], 'd': [], 'e': []}
# 临时构建的列表;


In [6]: d1 = {k:[] for k in 'abcde'}
In [7]: d1
Out[7]: {'a': [], 'b': [], 'c': [], 'd': [], 'e': []}
# 拿一个key出来、临时定义一个列表
x = ['a',1,'b',20,'c',32]
def fn(x):
    return x if isinstance(x,int) else int(x,16)

print(sorted(fn(x=x))
# 改造为匿名函数
print(sorted(x,key=lambda x: x if isinstance(x,int) else int(x,16)))

生成器函数

生成器对象:

  1. 生成器表达式,每一次生成器表达式执行一次都会得到一个全新的生成器对象;
  2. 生成器函数,每一次函数调用都会得到全新的生成器对象。只要有yield语句的函数都是生成器函数;
  3. 生成器函数,每一次执行到yield这一句,把yield的值返回;
  4. return非常强势,见到它函数就完成执行了、如果你用next驱动生成器对象,碰到了return,抛出StopIteration异常,用for就不会因为for循环会友好的退出;
  5. 生成器函数惰性本身是推荐的,还有他用在了协程中,线程、进程之后;
#!/bin/env python3
def generate_numbers(n):
    for i in range(n):
        yield i

my_generate = generate_numbers(5)

for number in my_generate:
    print(number)

'''以上代码,使用yield关键字,将函数变成了一个生成器,每次调用next()方法,就会执行一次函数,并返回一个值,直到函数执行完毕,抛出StopIteration异常,表示生成器执行完毕''

应用

  • 无限容器

所以生成器函数元素可以是有限个对象、也可以是无限个;

'''生成器函数无限容器,可作用为id生成器'''
def foo():
    count = 0
    while True:
        count += 1
        yield count

my_foo = foo()

for i in my_foo:
    print(i)
    print('\n')
    if i > 100:
        break
  • 计数器
'''计数器'''
def inc():
    def foo(): # id生成器
        count = 0
        while True:
            count += 1
            yield count
    c = foo()
    return c

x = inc()
print(next(x))
print(next(x))

'''方法二'''
def inc():
    def foo(): # id生成器
        count = 0
        while True:
            count += 1
            yield count
    c = foo()
    return lambda : next(c)

x = inc()
print(x())
print(x())

yield 方法简写

def foo():
    yield from range(10)

for x in foo():
    print(x)

'''以上等同于'''

def foo():
    for i in range(10):
        yield i

for x in foo():
    print(x)

'''yield from 语法,可以将一个生成器,转换成一个迭代器,并且将生成器中的值,全部返回'''
def foo():
    yield from map(lambda x: x+100 , range(10))

for x in foo():
    print(x)
test_dict = dict(map(lambda x,y: (x, y+100), 'abcde', range(10)))
print(test_dict)

高阶函数;

def counter(base):
    def inc(step=1):
        nonlocal base
        base += step
        return base
    return inc

f = counter(100)
print(f(10))
print(f(10))
# 结果为110,120
# 高阶函数,返回一个函数,这个函数可以在原来的基础上,进行累加;
  • 柯里化
'''柯里化'''

def add(x):
    def fn(y):
        return x + y
    return fn

print(add(10)(20))

wraps

from functools import wraps
def logger(fn):
    @wraps(fn)
    def inner(*args,**kwargs):
        '''
        add description
        这个warpper函数的描述
        '''
        print(fn.__name__,args,kwargs)
        print('执行前可以做的事情,增强')
        ret = fn(*args,**kwargs)
        print('执行后可以做的事情,增强')
        return ret
    return inner
logger_add = logger(add)(4,y=100)
print(logger_add)


@logger # 等价式 , add = logger(add)
def add(x,y:int):
    '''
    add description
    这add函数的描述
    '''
    return x + y

print(add.__name__, add.__doc__, add.__annotations__)
# 注意这里的结果
add (4,) {'y': 100}
执行前可以做的事情,增强
执行后可以做的事情,增强
104
add 
    add description
    这add函数的描述
     {'y': <class 'int'>}

评论