首页 > 代码库 > 装饰器、包的导入

装饰器、包的导入

python2 存在内存里的 字符串就是bytes,bytes就是字符串, 需要先解码(decode),再编码(encode)

python3 字符串 = unicode, bytes = py2 bytes, 不需要解码,自动转成unicode编码(没有decode方法) 如果需要转成别的格式,可以加上encode 默认文件编码utf-8, 变量的编码unicode

二进制--> bytes --> 字符编码的格式

一、为什么使用函数之模块化程序设计

不使用模块的缺点:

  1. 体系结构不清晰,可读性差
  2. 可扩展性差
  3. 程序冗长

二、定义函数

def func(args):
		‘‘‘文档描述‘‘‘
		函数体
		return 返回值
		
1. 无参函数
	def foo():
		print(‘in the foo‘)
	foo()
	
2. 有参函数
	def bar(x,y):
		print(‘in the bar‘)
	bar(1,2)
	
3. 定义空函数
	def func():
		pass

三、调用函数

1. 语句形式:类似无参函数
2. 表达式的形式
	def my_max(x,y):
		if x>y:
			return x
		else:return y
	res=my_max(1,2) # 语句形式
	res1 = 10*my_max(1,2) # 表达式形式
	
3. 作为另一个函数的参数
	my_max(1,my_max(2,3))

四、返回值

1. 不定义返回值,返回none
2. 返回一个
	def foo():
		return 1
	res=foo()
	print(res)
	
3. 返回多个
	def foo():
		return 1,‘s‘,[2,3]
	res=foo()
	print(res)
	#返回元祖形式

五、函数的参数

1、形参

def func(x,y):
	print(x)
	print(y)

2、实参

func(1,2)

3、从实参的角度

def foo(x,y):
    print(x,y)
		
foo(1,2) # 按位置传参
foo(y=10,x=‘a‘) # 按照key=value关键字形式
	
# 针对同一个形参,必须采用按位置或关键字为形参传值
# 按照位置
foo(y=2,1) # 错误

4、从形参的角度:位置参数,默认参数,可变长参数,**kwargs

def foo(x,y,z): # 位置参数:必传值参数
	print(x,y,z)
foo(y=2,x=1,z=3)
	
def foo(x,y=3): # 默认参数,定义的参数放在未定义参数后面
	print(x,y)
foo(1) # 打印 1 3

5、可变长参数 *args

# 实参按照位置
def foo(x,y,*args):
	print(x)
	print(y)
	print(args)
#1
foo(1,2,3,4,5,6,7)
#2
l=[3,4,5]
foo(1,2,*l) # 带*的方式

def foo(x,**kwargs): 
	print(x)
	print(kwargs)
foo(1,y=3,z=1) # 不能对同一个形参赋值,如再加一个x=2
		dic = {‘a‘:1,‘b‘:2}
		foo(1,**dic)
		
		def foo(x,y,z):
			print(x,y,z)
		foo(**{‘x‘:1,‘z‘:3,‘y‘:2}) # foo(x=1,y=2,z=3) key要对应形参
		
		
# 位置参数 --> 默认参数,*args,**kwargs
# *args 等同于 展开按照位置的方式
# **kwargs 等同于 把kwargs展开按照关键字的方式

六、闭包函数

def page(url):
	def get():
		pass
	return get

装饰器

在遵循下面两个原则的前提下为被修饰者添加新功能,必须遵循两个原则:

  1. 一定不能修改源代码
  2. 不能修改调用方式

假设为index功能添加一个统计时间的功能

@timer # index=timer(index)
def index():
    print(‘in the index‘)

index()

# func1=deco1(index) --> func2=doco2(func1) --> func3=doco3(func2)
# 独立一行,从下往上调用
@deco3
@deco2
@deco1
def index():
    print(‘in the index‘)

index() # 最后调用deco3

用例

import time
def timer(func): # 只能一个参数,并且是被装饰的函数
    def wrapper():
        start_time = time.time()
        func() # 运行原始的index
        time.sleep(3)
        stop_time = time.time()
        print(‘run time is %s‘     %(stop_time-start_time))
    return wrapper

@timer
def index():
    print(‘in the index‘)
index()
# 这个用例中,没有改变index函数的代码及调用方式

无参装饰器

import time
import functools
def timer(func):
    @functools.wraps(func)
    def wrapper(*args,**kwargs): # ‘tom‘,23 --> (‘tom‘),{‘age‘:23}
        ‘‘‘
        wrapper func
        :param args:
        :param kwargs:
        :return:
        ‘‘‘
        start_time = time.time()
        # func() # 运行原始的index
        res=func(*args,**kwargs)
        # time.sleep(3)
        stop_time = time.time()
        print(‘run time is %s‘ %(stop_time-start_time))
        return res
    return wrapper
@timer
def index(msg):
    ‘‘‘
    index func
    :param msg:
    :return:
    ‘‘‘
    print(‘in the index‘,msg)
index(‘hello world‘)
@timer
def home(user,age):
     print(‘%s is %s years old‘ %(user,age))
    return 1
res = home(‘tom‘,age=23)
print(res)
print(help(index))

练习登陆官网

def auth(func):
    def login():
        un = ‘tommy‘
        pw = ‘anyway‘
        while 1:
            username = input(‘username>>: ‘).strip()
            passwd = input(‘password>>: ‘).strip()
            if username == un and passwd == pw:
                print(‘welcome to oldboy,‘, username)
                res = func()
                return res
            if username == ‘quit‘:
                break
    return login

@auth
def wel():
    print(‘官网,‘.center(20,‘-‘))
    return 1

welcome = wel()
print(welcome)

模块

import spa
print(spa.money)
spa.mo()

第一次导入模块做了三件事

  1. 创建新的作用域
  2. 在该作用域内执行顶级代码
  3. 得到一个模块名,绑定到该模块内的代码

为模块起别名

import spa as sp
print(sp.money)

一行导入多个

import re,os

from ... import...

from spa import mo
mo(5)

from ... import ... as ...

from spa import mo as m

from ... import *

spa文件中有:
__all__ = [‘mo‘,‘haha‘] # * 调用时只允许调用列表里的模块
另一个脚本调用时:
from spa import * # 下划线开头的无法被*导入
print(mo(10))
print(haha())
print(_change()) # name ‘_change‘ is not defined
print(bacc()) # 因为spa里定义了只允许调用的模块,这个会报错

导入模块顺序

  1. 内置函数(built-in)
  2. sys.path
  3. 附加函数

在sys.path中添加自定义目录

import sys
sys.path.insert(0,‘test_dir‘)

包的导入

import glance.db.models as db_model
db_model.register_models(‘mysql‘)

from glance.db.models import register_models
register_models(‘MySQL‘)

from glance.api import *
# 先导glace的init文件
# 再导api的init文件

绝对导入

from glance.db import models

相对导入

#在cmd目录程序中导入db目录的模块
from ..db import models

关于__name__

print(__name__)
# 把文件当作脚本执行__name__等于‘__main__‘
# 把文件spa.py当作模块去使用__name__等于模块名‘spa‘

if __name__ == ‘__main__‘:
    print(‘文件被当作脚本执行时触发的代码‘)

 

装饰器、包的导入