0%

缘起

  • 因为不知道做错了什么事遭到了可敬的人的讨厌, 这样的事于我已不鲜见, 然而心情还是难以平复的, 好像再次变回了曾经的顽劣少年.
  • 好在babun下配置git-zsh的成功, 多多少少平复了一点苦辛.
阅读全文 »

装饰器的实例1-代码计时器,说明都写在代码注释中了~

import time

def timer(func):
def wrapper(*arguments,**keyword_arguments): # 参数有无与多少不确定, 关键字参数有无与多少不确定
start=time.time()
ret=func(*arguments,**keyword_arguments) # 与前文类似, 参数有无与多少不确定
end=time.time()
print('FuncName:{};\nResult:{}\nTime Spent:\t{}s'.format(getattr(func,'__name__'),ret,end-start),file=open('D:\跑速情况.txt','a'))
# 可以先dir(func) 查出func有__name__这个attr, 于是用函数getattr(funcName, funcAttrName)
return ret # 很关键, 因为func有返回值所以要写ret(其实没有返回值也写一下没什么问题)
return wrapper # 装饰器本质: ret内层函数

# 注意: 带参数的装饰器指的是装饰器有参数, 就是最外层的timer(func,args),
## 被装饰函数有参数, 直接在内部处理就可以, ret=func(*arguments,**keyword_arguments)

@timer
def m1_feibonaqi(n,visited=[]): # 改进版递归型斐波那契, 区分于远坂sb无脑递归型在于加入visited使得不用重复计算
if n==1 or n==2:
return 1
else:
if bool(visited)==0:
ori_visited=[1,1].extend([None for each in range(3,n+1)])
visited=ori_visited
else:
if visited[n-2]==None:
tail=m1_feibonaqi(n-2)
visited[n-2]=tail
if visited[n-1]==None:
head=m1_feibonaqi(n-1)
visited[n-1]=head
return visited[n-1]+visited[n-2]
return m1_feibonaqi(n-1)+m1_feibonaqi(n-2)

@timer
def m1_feibonaqi(n): # sb无脑递归型, 可以拿来测下栈帧深度
if n==1 or n==2:
return 1
else:
return m1_feibonaqi(n-1)+m1_feibonaqi(n-2)

@timer
def m2_feibonaqi(n): # 正常型斐波那契
if n==1 or n==2:
return 1
else:
f1,f2=1,1
head,tail=f2,f1
cnt=2
while cnt<n:
cnt+=1
next_val=head+tail
head,tail=next_val,head
return next_val

@timer
def m3_feibonaqi(n,visited=[]): # 改进版递归型斐波那契, 区分于远坂sb无脑递归型在于加入visited使得不用重复计算
if n==1 or n==2:
return 1
else:
if bool(visited)==0:
ori_visited=[1,1].extend([None for each in range(3,n+1)])
visited=ori_visited
else:
if visited[n-2]==None:
tail=m1_feibonaqi(n-2,visited)
visited[n-2]=tail
if visited[n-1]==None:
head=m1_feibonaqi(n-1,visited)
visited[n-1]=head
return visited[n-1]+visited[n-2]
return m3_feibonaqi(n-1,visited)+m3_feibonaqi(n-2,visited)


m1_feibonaqi(10) # 这个只能跑20以内的
print('----分界线12----',file=open('D:\跑速情况.txt','a'))
m2_feibonaqi(10**5) # 这个可以跑10万以内的
print('----分界线23----',file=open('D:\跑速情况.txt','a'))
m3_feibonaqi(10) # 这个也同样只能跑20以内的

## 实际上m1和m3跑出来结果是一样的(^7$7^), 难受~
阅读全文 »

  • 缘起
    • 日志与函数计时功能的实现
    • 学弟问起此话题,自己也感到初学时颇费功夫.
  • 背景
    • 返回同类指针: 装饰器本质只是函数or类, 唯一不同之处只在于返回值是函数指针or类指针
    • @符号: 装饰器的”@”符号没什么特别, 完全等价于(目标函数定义好后)把目标函数作为实参传进装饰器(再赋值给函数变量)
      • 装饰-赋值: bar=decorator(bar)
      • 调用装饰后函数: bar()
    • “插件”本质: 其他函数与装饰器关系独立, 装饰器执行不依赖也不影响其他函数的功能.
  • Demo理解
# 函数实体的存在是既定的, 不依赖于特定函数名.
import copy

def greet(name):
return 'Nice to meet you, '+name

print(greet)
# out: <function greet at 0x00000259C5FAD1E0>
## 函数实体已建立, 是<function greet at 0x00000259C5FAD1E0>
## 此时, greet仅仅是一个变量名, 一个函数指针, 它指向的函数对象是<function greet at 0x00000259C5FAD1E0>

sayNiceToMeetYou=greet
# python默认是浅复制, 事实上sayNiceToMeetYou与greet指向同一个对象, 该对象类型是函数

print(id(sayNiceToMeetYou),id(greet))
## out: 1980378239456 1980378239456, 符合假设

del greet

print(sayNiceToMeetYou('lkr'))
# out: Nice to meet you, lkr, 说明仅仅删除指针, 函数实体并没有被删除

## 正戏开始

def decorator(func):
def wrapper_who_return_funcPtr():
# 返回参数列表: `https://web.archive.org/web/20210512042121/https://www.cnblogs.com/snow-backup/p/11077917.html`
# inspect库: `https://web.archive.org/web/20220605125226/https://docs.python.org/3/library/inspect.html`
print('before {} works.'.format(decorator.__code__.co_varnames[0]))
func()
print('After {} works.'.format(decorator.__code__.co_varnames[0]))
return wrapper_who_return_funcPtr

decorator(sayNiceToMeetYou)

# d_sayNiceToMeetYou=copy.deepcopy(sayNiceToMeetYou)
# # print(id(sayNiceToMeetYou),id(d_sayNiceToMeetYou))
## out: 2303771464160 2303771464160, 没有新对象生成, 难道深拷贝也出了问题吗?
## 答案找到了: `https://web.archive.org/web/20220525023657/https://docs.python.org/3.7/library/copy.html` 搜索"It does “copy” functions and classes (shallow and deeply), by returning the original object unchanged"

阅读全文 »

  • 缘起
  • 结论
    • import搜索目录为sys.path这个列表
      • 由于是列表所以可以更改, 比如加入github.io文件夹什么的
      • sys.path的改变不跨文件, 可以拿两个py文件自己试下
    • 使用M模块中途M模块被修改, 使用imp.reload(module)进行模块的重新导入
      • 质疑: 是否本就不应该在使用某个模块的中途去修改这个模块
      • 全模块导入时存在模块依赖: 如果M模块自身也import了其他模块M1,M2, 那么这些M1,M2并不会被导入: 详见python全模块reload的坑
    • 避免循环引用
      • 循环引用: 存在a.py与b.py, 此时a.py中写import b同时b.py中写import a
      • 设计观点: “类-接口”模式的重要性, 包括:
        • 类C1,C2,C3…不互相import对方
        • import工作完全由接口实现, 接口I1,I2也要做到相对独立

以前没有使用标准指法, 导致打字速度无法提升. 由于近期较为清闲, 于是开始着手练习打字, 一是为了日后代码能够勤写注释, 二是为了考托福.

训练网站: keybr.com; 感谢知乎小伙伴@何明涛;

阅读全文 »

  • 缘起

  • 背景

    • 众所周知, python默认进行浅拷贝, 而深拷贝需要动用copy模块下的copy.deepcopy
    • 深浅拷贝的实质区别在于是否生成了新的对象, 深拷贝生成了新的对象, 浅拷贝在同一个对象上增加了一个引用
    • 不同对象可以由id进行区分
  • 结论

    • deepcopy作用于容器时, 深拷贝是递归进行的
    • copy.copy作用于容器时
      • 容器是可变对象, 此时copy.copy只对第一层进行深拷贝, 其余浅拷贝
      • 容器是不可变对象, 此时copy.copy对容器整体进行浅拷贝
  • 演示

import copy
# l for list

l1,l2=[1,2,3],[1,2,3]
print('l1:{};\tl2:{}'.format(id(l1),id(l2)))
l12=[l1,l2]

d_l12=copy.deepcopy(l12)

print('l12:{};\td_l12:{}'.format(id(l12),id(d_l12))) # deepcopy外壳实现了深拷贝
print('l1:{};\tl12元素0:{};\td_l12元素0:{}'.format(id(l1),id(l12[0]),id(d_l12[0]))) # deepcopy内部元素同样也实现了深拷贝:l12的元素0就是l1对象本身; 而d_l12元素0不是l1对象
# 由于l2也是同样的情况, 所以就不演示了

# cc for copy_copy obj

cc_l12=copy.copy(l12)

print('l12:{};\tcc_l12:{}'.format(id(l12),id(cc_l12))) # 对l12可变对象: copy.copy外壳实现了深拷贝
print('l1:{};\tl12元素0:{};\tcc_l12元素0:{}'.format(id(l1),id(l12[0]),id(cc_l12[0]))) # copy.copy内部元素仅仅实现了浅拷贝:l12的元素0就是l1对象本身; 而cc_l12元素0也是l1对象本身

# t for tuple
t12=(l1,l2)
cc_t12=copy.copy(t12)
print('t12:{};\tcc_t12:{}'.format(id(l12),id(cc_l12))) # 对t12可变对象: copy.copy外壳仅实现浅拷贝
print('l1:{};\tt12元素0:{};\tcc_t12元素0:{}'.format(id(l1),id(l12[0]),id(cc_l12[0]))) # copy.copy内部元素也仅仅实现了浅拷贝:t12的元素0就是l1对象本身; 而cc_t12元素0也是l1对象本身
阅读全文 »

  • 缘起
    • 办理移动业务时, 通过往日流水发现自己每月账单是88元,多花了不少冤枉钱.
    • 办理移动业务途中, 使用百度地图搜索营业厅, 到目的地后才发现没有开门.
    • 办理移动业务时, 产生”一体化”想法

  • 缘起:

    • 前文我们尝到了函数化的甜头, 于是我们考虑”处处函数化”的方案
  • 思路:

    • alias要保留, 函数可以实现复合功能, 但是单一功能还得由alias负责, 这些单一功能是不能被革命的
    • 函数直接写在bashrc里面, 一共就没几个函数, 但是注释要写好
  • 流程:

    • 设计两个函数, uguh(upload github & upload hexo)和ohn(outside hexo new)
    • 传参是字符串最好用变量接收一下, 增强可读性github自动上传脚本
  • 图示