本节内容

  1. 上节内容回顾(函数)
  2. 装饰器
  3. 模块

1.上节内容回顾(函数)

函数

1.为什么要用函数?

使用函数之模块化程序设计,定义一个函数就相当于定义了一个工具,需要用的话直接拿过来调用。
不使用模块化程序设计的缺点:

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

2.定义函数分三种

  1. # -*- coding: UTF-8 -*-
  2. #blog:http://www.cnblogs.com/linux-chenyang/
  3. #
  4. #1.无参函数
  5. def foo():
  6. print('in the foo')
  7.  
  8. foo()
  9.  
  10. #2.有参函数
  11. def bar(x,y):
  12. print('in the bar')
  13.  
  14. bar(1,2)
  15.  
  16. #3.定义空函数
  17. def func():
  18. pass
  19.  
  20. def get():
  21. pass
  22.  
  23. def put():
  24. pass

展开

3.调用函数分三种

  1. # -*- coding: UTF-8 -*-
  2. #blog:http://www.cnblogs.com/linux-chenyang/
  3. #
  4. #1.语句形式
  5. def foo():
  6. print('in the foo')
  7.  
  8. foo()
  9.  
  10. #2.表达式的形式
  11.  
  12. def my_max(x,y):
  13. if x > y:
  14. return x
  15. else:
  16. return y
  17.  
  18. res = my_max(1,2)
  19. res = 10*my_max(1,2)
  20.  
  21. #3.作为另外一个函数的参数
  22. my_max(1,my_max(2,3))

展开

4.函数返回值的三种形式

  1. # -*- coding: UTF-8 -*-
  2. #blog:http://www.cnblogs.com/linux-chenyang/
  3. #
  4. #1.如果不定义返回值,则返回值为空。
  5. def foo():
  6. pass
  7.  
  8. res = foo()
  9. print(res)
  10.  
  11. #2.返回一个值,返回值可以是任意的数据类型
  12. def foo():
  13. return 1
  14.  
  15. res = foo()
  16. print(res)
  17.  
  18. #3.返回多个值
  19. def foo():
  20. return 1,'w',[1,2,3]
  21.  
  22. res = foo()
  23. print(res)

展开

5.函数的参数

  1. # -*- coding: UTF-8 -*-
  2. #blog:http://www.cnblogs.com/linux-chenyang/
  3. #
  4. #形参和实参的对应关系:
  5. #实参是真是占用内存空间的func(1,2)
  6. #形参只有在函数调用的时候才会接收值,占用内存空间,等函数调用完就会释放。
  7.  
  8. def func(x,y):
  9. print(x)
  10. print(y)
  11.  
  12. func(1,2)
  13. func(1,'a')
  14.  
  15. #形参和实参的动态性:定义形参的时候不用指定数据类型
  16. #坏处:不指定数据类型,若执行以下代码会报错
  17. def test(x,y):
  18. return x+y
  19.  
  20. test(1,'a')
  21.  
  22. #解决方法一:
  23. def test(x,y):
  24. if type(x) is int and type(y) is int:
  25. return x+y
  26.  
  27. test(1,'a')
  28. #解决方法二:添加注释
  29. def test(x,y):
  30. '''
  31.  
  32. :param x: int
  33. :param y: int
  34. :return:
  35. '''
  36. return x+y
  37.  
  38. test(1,'a')

展开

6.位置参数,默认参数,*args,**kwargs

  1. #从实参的角度:针对同一个形参,我们要么按照位置要么按照关键字为形参传值,不能对同一个形参赋值
  2.  
  3. # def foo(x,y):
  4. # print(x,y)
  5. #
  6. # foo(1,2) #按位置
  7. # foo(y=2,x=1) #按照关键字的形式,必须写在位置关系的后边
  8.  
  9. #从形参的角度:位置参数,默认参数,可变长参数*args,**kwargs
  10.  
  11. # def test(x,y,z): #位置参数,必传值参数
  12. # print(x)
  13. # print(y)
  14. # print(z)
  15. #
  16. # test(1,y=2,z=3)
  17.  
  18. # def test2(x,y=1): #默认参数
  19. # print(x)
  20. # print(y)
  21. #
  22. # test2(1,2)
  23. # test2(1)
  24.  
  25. # def test3(x,y=1,*args): #*args 必须放在在默认参数后面,会将多余的组成一个元组的形式
  26. # print(x)
  27. # print(y)
  28. # print(args)
  29. #
  30. # test3(1,2,3,4,5,6,7,8,9,)
  31. # l = ['a','b']
  32. # test3(1,2,*l) #*args的形式就等于1,2,3,4,5.l
  33. # test3(1,2,'a','b') #*args的形式就等于1,2,3,4,5
  34. # l = ('a','b')
  35. # test3(1,2,*l) #l可以是列表,可以是元组,结果都一样
  36.  
  37. # def test3(x,y,z): #*的用法
  38. # print(x,y,z)
  39. #
  40. # l=[1,2,3]
  41. # test3(*l) #等同于test3(1,2,3)
  42.  
  43. # def foo(x,**kwargs): #**kwargs的用法
  44. # print(x)
  45. # print(kwargs)
  46. #
  47. # foo(1,y=2,z=3)
  48. # dic = {'a':1,'b':2}
  49. # foo(1,**dic) #等同于foo(1,a=1,b=2)
  50.  
  51. #位置参数>默认参数>*args>**kwargs
  52.  
  53. def func(x,*args,**kwargs): #这样定义就表示函数可以传任意的参数。
  54. print(x)
  55. print(args)
  56. print(kwargs)

展开

总结:

  *sym 等同于展开按照位置的方式去写

  **sym 等同于把sym展开按照关键字的方式去写

7.函数是第一类对象:意思就是函数可以被当做数据来传递

这样执行为什么不会报错?因为函数就和变量一样,将qasd...赋值给了fun,只有在调用的时候才会检查其中的语法是否正确。

结论:

  • 函数的定义和变量的定义是一回事,变量有什么特性,函数就有什么特性
  1. # -*- coding: UTF-8 -*-
  2. #blog:http://www.cnblogs.com/linux-chenyang/
  3. #
  4. #函数是第一类对象
  5. def func():
  6. print('in the func')
  7.  
  8. # #1.可以被引用
  9. # f1=func
  10. # f1()
  11.  
  12. #2.可以作为参数(高阶函数)
  13. def foo(x):
  14. x()
  15.  
  16. foo(func)
  17.  
  18. #3.返回值可以是函数
  19. def foo1():
  20. return func
  21. res=foo1()
  22. res()
  23.  
  24. #4.可作为容器类型的元素
  25. func_dic={
  26. 'func':func
  27. }
  28.  
  29. func_dic['func']()

展开

8.函数的嵌套

  1. # -*- coding: UTF-8 -*-
  2. #blog:http://www.cnblogs.com/linux-chenyang/
  3. #
  4. #嵌套调用:在一个函数的内部调用另外一个函数
  5. #举列:比较四个数的大小
  6. def my_max4(a,b,c,d):
  7. res1=my_max2(a,b)
  8. res2=my_max2(res1,c)
  9. res3=my_max2(res2,d)
  10.  
  11. return res3
  12.  
  13. def my_max2(x,y):
  14. if x > y:
  15. return x
  16. else:
  17. return y
  18.  
  19. print(my_max4(1,2,100,-1))
  20.  
  21. #嵌套定义
  22. x=1
  23. def f1():
  24. x=10
  25. def f2():
  26. x=100
  27. print(x)
  28.  
  29. return f2
  30.  
  31. func=f1()
  32. func()

展开

9.闭包函数

  1. # -*- coding: UTF-8 -*-
  2. #blog:http://www.cnblogs.com/linux-chenyang/
  3.  
  4. #闭包函数:打包内部函数(f2)的时候包含对外部作用域名字的引用(x=1),f2就被称为闭包函数
  5. #用处:什么使用用,什么时候执行就可以了
  6.  
  7. def f1():
  8. x=1
  9. def f2():
  10. print(x)
  11.  
  12. return f2
  13.  
  14. f=f1()
  15. x=100000000000
  16. f()
  17.  
  18. #举列:获取baidu的页面
  19. from urllib.request import urlopen #导入模块
  20.  
  21. def page(url):
  22. # url='http://www.baidu.com'
  23. def get():
  24. return urlopen(url).read().decode('utf-8')
  25. return get
  26.  
  27. baidu=page('http://www.baidu.com')
  28. print(baidu())

展开

2.装饰器

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

  1. 一定不能修改源代码
  2. 不能修改调用方式
  1. #语法如下:就相当于将index传递给func,然后wrapper的结果给了timer()函数,然后timer函数就等于index
  2. #举列:给原始的函数index显示出运行的时间
  3.  
  4. import time
  5. def timer(func):
  6. def wrapper():
  7.  
  8. start_time = time.time()
  9. func() #这个就是在调用最原始的函数
  10. stop_time = time.time()
  11. print('run time is %s' %(start_time-start_time))
  12.  
  13. return wrapper
  14.  
  15. @timer #index=time(index)
  16. def index():
  17. print('in the index')
  18.  
  19. index()

展开

  1. #举列:传人多个参数和返回值的用法
  2. import time
  3. def timer(func):
  4.  
  5. def wrapper(*args,**kwargs): #('test'),{'msg'='tom'}
  6.  
  7. start_time = time.time()
  8. res=func(*args,**kwargs) #home('test',msg='tom')---->home(user,msg)
  9. # func(msg) #这个就是在调用最原始的函数
  10. stop_time = time.time()
  11. print('run time is %s' %(start_time-start_time))
  12. return res
  13. return wrapper
  14.  
  15. @timer #index=time(index(msg))
  16. def index(msg):
  17. print('in the index',msg)
  18.  
  19. @timer
  20. def home(user,msg):
  21. print('in the home %s %s' %(user,msg))
  22. return 1
  23.  
  24. index('hello world')
  25. home('test',msg='tom')
  26.  
  27. res=home('test',msg='tom')
  28. print(res)

展开

  1. #装饰器小知识:默认被装饰器的注释信息不会被调用,只会调用wrapper里的信息
  2. #解决方法:导入functools,然后在wrapper上面在装饰
  3.  
  4. import time,functools
  5.  
  6. def timer(func):
  7. @functools.wraps(func)
  8. def wrapper(*args,**kwargs): #('test'),{'msg'='tom'}
  9. '''
  10. wrapper func
  11. :param args:
  12. :param kwargs:
  13. :return:
  14. '''
  15. start_time = time.time()
  16. res=func(*args,**kwargs) #home('test',msg='tom')---->home(user,msg)
  17. stop_time = time.time()
  18. print('run time is %s' %(start_time-start_time))
  19. return res
  20. return wrapper
  21. @timer #index=time(index(msg))
  22. def index(msg):
  23. '''
  24. 注释信息
  25. :param msg:
  26. :return:
  27. '''
  28. print('in the index',msg)
  29. return 1
  30. res=index('hello world')
  31. print(res)
  32. print(help(index))

展开

  1. # -*- coding: UTF-8 -*-
  2. #blog:http://www.cnblogs.com/linux-chenyang/
  3. #需求:我要想执行index,必须先让我输入正确的用户名和密码才能让你执行
  4.  
  5. # def auth(func):
  6. # def wrapper(*args,**kwargs):
  7. # user = 'root'
  8. # passwd = 'root123'
  9. # newuser = input('user:')
  10. # newpasswd = input('passwd:')
  11. # if user == newuser and passwd == newpasswd:
  12. # return func(*args,*kwargs)
  13. # return wrapper
  14. #
  15. # @auth
  16. # def index(msg):
  17. # print("helo : %s" %(msg))
  18. #
  19. #
  20. # index('lijun')
  21.  
  22. #有参数的装饰器
  23. #需求:现在我的index函数程序基于两种的验证方式,我的用户名和密码有可能是保存在本地,有可能是保存在数据库
  24.  
  25. def auth_test(type):
  26. def auth(func):
  27. def wrapper(*args,**kwargs):
  28. user = 'root'
  29. passwd = 'root123'
  30. newuser = input('user:')
  31. newpasswd = input('passwd:')
  32. if type == 'mysql':
  33. print('这个是mysql的验证方式')
  34. return func(*args,**kwargs)
  35. elif type == 'file':
  36. if user == newuser and passwd == newpasswd:
  37. return func(*args,*kwargs)
  38. else:
  39. pass #可以是其他的验证方式
  40. return wrapper
  41. return auth
  42.  
  43. @auth_test('file') #等同于auth_test(mysql)-->执行的结果假如为res---->@res index=auth(index)
  44. def index(msg):
  45. print("helo : %s" %(msg))
  46.  
  47. index('lijun')

展开

  1. #需求:假如我还有个函数,我第一次已经登陆成功过,在运行这个函数就不需要我在输入用户名和密码
  2. #应用场景:假如你已经登陆了京东,在打开第二个页面是否还让你输入用户名和密码
  3.  
  4. accounts = {} #先定义一个字典,登陆成功后就加进去
  5. current_login_user = None #定义一个全局变量,登陆成功后改这个变量
  6.  
  7. def auth_test(type):
  8. def auth(func):
  9. def wrapper(*args,**kwargs):
  10. if current_login_user not in accounts: #判断是否已经认证成功
  11. user = 'root'
  12. passwd = 'root123'
  13. newuser = input('user:')
  14. newpasswd = input('passwd:')
  15. if type == 'mysql':
  16. print('这个是mysql的验证方式')
  17. return func(*args,**kwargs)
  18. elif type == 'file':
  19. if user == newuser and passwd == newpasswd:
  20. accounts[user] = passwd #给字典传值{'root':'root123'}
  21. global current_login_user #先声明改这个全局变量
  22. current_login_user = user
  23. return func(*args,*kwargs)
  24. else:
  25. return func(*args,**kwargs)
  26.  
  27. return wrapper
  28. return auth
  29.  
  30. @auth_test('file') #等同于auth_test(mysql)-->执行的结果假如为res---->@res index=auth(index)
  31. def index(msg):
  32. print("helo : %s" %(msg))
  33.  
  34. @auth_test('mysql')
  35. def home():
  36. print('This is home')
  37.  
  38. index('lijun') #运行第一个函数
  39. home() #运行第二个函数

展开

3.模块

什么是模块?

  一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀

为什么要用模块?

  如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script。

随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用.

如何使用模块?

3.1.import

>示例:spam.py,文件名spam.py,模块名spam

  1. #spam.py文件
  2.  
  3. print('There is spam')
  4. mony = 100
  5.  
  6. def read():
  7. print(mony)
  8.  
  9. ###################################
  10. #在另外一个python脚本操作
  11. #import spam
  12. #import spam     #只会执行spam
  13.  
  14. import spam
  15. print(spam.mony)
  16. spam.read()
  17.  
  18. '''
  19. 第一次导入模块做了三件事:
  20. 1.创建新的作用域
  21. 2.在该作用域中执行顶级代码
  22. 3.得到一个模块名,绑定到该模块内的代码
  23. '''
  24.  
  25. #输出:
  26. There is spam
  27. 100
  28. 100

>导入的模块只对该模块的作用域有效

  1. #spam.py
  2. money = 100
  3.  
  4. def change(): #修改全局变量
  5. global money
  6. money = 0
  7.  
  8. #另外一个脚本操作
  9. import spam
  10.  
  11. mony = 100000
  12. spam.change()
  13. print(mony)
  14.  
  15. #输出:
  16. 100000

>为模块名起别名,相当于m1=1;m2=m1

  1. import spam as sm
  2. print(sm.money)

  为已经导入的模块起别名的方式对编写可扩展的代码很有用,假设有两个模块xmlreader.py和csvreader.py,它们都定义了函数read_data(filename):用来从文件中读取一些数据,但采用不同的输入格式。可以编写代码来选择性地挑选读取模块,例如

  1. if file_format == 'xml':
  2. import xmlreader as reader
  3. elif file_format == 'csv':
  4. import csvreader as reader
  5. data=reader.read_date(filename)

>一行当中导入多个模块

  1. import sys,os,re

3.2.from...import....    缺点:容易重名

>用法,直接调用,不需要前面加模块名

  1. #spam.py
  2. money = 100
  3.  
  4. def change(): #修改全局变量
  5. global money
  6. money = 0
  7.  
  8. #另外一个脚本操作
  9. from spam import change
  10.  
  11. mony = 100000
  12. change()
  13. print(mony)
  14.  
  15. #输出:
  16. 100000

>若函数和当前的脚本重名,会执行当前的函数

  1. #spam.py
  2. def change():
  3. print("spam里的函数")
  4.  
  5. #另外一个脚本
  6. from spam import change
  7.  
  8. def change():
  9. print("当前的脚本")
  10.  
  11. change()
  12.  
  13. #输出
  14. 当前的脚本

>也支持as,也支持导入多行

  1. from spam import read1 as read
  2.  
  3. from spam import (read1,
  4. read2,
  5. money)

>from spam import * 把spam中所有的不是以下划线(_)开头的名字都导入到当前位置

  1. #spam.py
  2.  
  3. def change():
  4. print("spam里的函数")
  5.  
  6. def read1():
  7. print("from read1")
  8.  
  9. def _read2():
  10. print('from read2')
  11.  
  12. #另外一个脚本执行
  13. from spam import *
  14.  
  15. change()
  16. read1()
  17. _read2()
  18.  
  19. #输出:_read2会报错
  20. Traceback (most recent call last):
  21. File "D:/pycharm/s16/day4/模块导入.py", line 32, in <module>
  22. _read2()
  23. NameError: name '_read2' is not defined
  24. spam里的函数
  25. from read1

>__all__ 的用法,注意是两个下划线。

  1. #spam.py
  2. __all__ = ['read1','read3'] #只有用from spam import *的方法导入模块的时候,只允许调用里面的函数
  3.  
  4. def change():
  5. print("spam里的函数")
  6.  
  7. def read1():
  8. print("from read1")
  9.  
  10. def _read2():
  11. print('from read2')
  12.  
  13. def read3():
  14. print('from read3')
  15.  
  16. #另外一台脚本操作
  17. from spam import *
  18.  
  19. read1()
  20. read3()
  21. #change () #若要导入change模块会报错

3.3把模块当做脚本执行

我们可以通过模块的全局变量__name__来查看模块名:
当做脚本运行:
__name__ 等于'__main__'

当做模块导入:
__name__等于'spam'

作用:用来控制.py文件在不同的应用场景下执行不同的逻辑
if __name__ == '__main__':

  1. #spam.py
  2. print(__name__)
  3. if __name__ == '__main__':
  4. print("文件被当做脚本执行时触发的代码")
  5. else:
  6. print("文件被当做模块模块时触发的代码")
  7.  
  8. #当做脚本执行的结果
  9. __main__
  10. 文件被当做脚本执行时触发的代码
  11.  
  12. #当做模块执行的结果,在另外一个脚本执行
  13. from spam import *
  14.  
  15. #输出
  16. spam
  17. 文件被当做模块模块时触发的代码

3.4 模块搜索路径

  1. #在D:\pycharm\s16\day4\dri'的目录下有个test_path.py的脚本
  2. print("这个是test_path模块")
  3.  
  4. #在D:\pycharm\s16\day4的目录下执行
  5. # -*- coding: UTF-8 -*-
  6. #blog:http://www.cnblogs.com/linux-chenyang/
  7.  
  8. '''
  9. import test
  10. 导入模块时首先要做的事情:
  11. 第一步:先去python内置的模块去找,看是否有该模块名。
  12. 第二步:然后去sys.path的目录按照顺序当中找是否有test的模块。
  13. '''
  14.  
  15. #举列,假如我在当前目录下建立个dir目录,想要在dir目录下执行test_path脚本
  16. import sys
  17. #print(sys.path)
  18. sys.path.append(r'D:\pycharm\s16\day4\dri')
  19. print(sys.path)
  20. #sys.path.insert(0,'/x/y/z') #排在前的目录,优先被搜索
  21.  
  22. import test_path
  23.  
  24. #输出
  25. ['D:\\pycharm\\s16\\day4', 'D:\\pycharm\\s16', 'C:\\Python35\\python35.zip', 'C:\\Python35\\DLLs', 'C:\\Python35\\lib', 'C:\\Python35', 'C:\\Python35\\lib\\site-packages', 'D:\\pycharm\\s16\\day4\\dri']
  26. 这个是test_path模块

至于.egg文件是由setuptools创建的包,这是按照第三方python库和扩展时使用的一种常见格式,.egg文件实际上只是添加了额外元数据(如版本号,依赖项等)的.zip文件。

需要强调的一点是:只能从.zip文件中导入.py,.pyc等文件。使用C编写的共享库和扩展块无法直接从.zip文件中加载(此时setuptools等打包系统有时能提供一种规避方法),且从.zip中加载文件不会创建.pyc或者.pyo文件,因此一定要事先创建他们,来避免加载模块是性能下降。

4.包

Packages are a way of structuring Python’s module namespace by using “dotted module names”
包是一种通过使用‘.模块名’来组织python模块名称空间的方式。

无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法

包的本质就是一个包含__init__.py文件的目录。
包A和包B下有同名模块也不会冲突,如A.a与B.a来自俩个命名空间

先建立如下结构的包和脚本内容:

  1. glance/ #Top-level package
  2.  
  3. ├── __init__.py #Initialize the glance package
  4.  
  5. ├── api #Subpackage for api
  6.  
  7. ├── __init__.py
  8.  
  9. ├── policy.py
  10.  
  11. └── versions.py
  12.  
  13. ├── cmd #Subpackage for cmd
  14.  
  15. ├── __init__.py
  16.  
  17. └── manage.py
  18.  
  19. └── db #Subpackage for db
  20.  
  21. ├── __init__.py
  22.  
  23. └── models.py
  1. 1 #文件内容
  2. 2
  3. 3 #policy.py
  4. 4 def get():
  5. 5 print('from policy.py')
  6. 6
  7. 7 #versions.py
  8. 8 def create_resource(conf):
  9. 9 print('from version.py: ',conf)
  10. 10
  11. 11 #manage.py
  12. 12 def main():
  13. 13 print('from manage.py')
  14. 14
  15. 15 #models.py
  16. 16 def register_models(engine):
  17. 17 print('from models.py: ',engine)

4.1注意事项

1.关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如item.subitem.subsubitem,但都必须遵循这个原则。

2.对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。

3.对比import item 和from item import name的应用场景:
如果我们想直接使用name那必须使用后者。

4.2 import和from....import导入包

  1. # -*- coding: UTF-8 -*-
  2. #blog:http://www.cnblogs.com/linux-chenyang/
  3. #验证的脚本是在glance同级别目录下
  4.  
  5. #import的方法导入,或者可以起别名
  6. import glance.db.models
  7. glance.db.models.register_models('mysql')
  8.  
  9. import glance.db.models as a
  10. a.register_models('起别名后的')
  11.  
  12. #from ... import ...的方法导入
  13. #需要注意的是from后import导入的模块,必须是明确的一个不能带点,否则会有语法错误,如:from a import b.c是错误语法
  14. from glance.db.models import register_models
  15. register_models('from的方法')
  1. #输出
  2. from models.py: mysql
  3. from models.py: 起别名后的
  4. from models.py: from的方法

4.3 __init__.py文件

不管是哪种方式,只要是第一次导入包或者是包的任何其他部分,都会依次执行包下的__init__.py文件(我们可以在每个包的文件内都打印一行内容来验证一下),这个文件可以为空,但是也可以存放一些初始化包的代码。

  1. #分别在glance下的__init_.py和db下的__init__.py写入内容
  2. #输出
  3. --------------glance package------------
  4. --------------db package------
  5. from models.py: mysql
  6. from models.py: 起别名后的
  7. from models.py: from的方法

4.4 from....import * 的用法

  1. #api/__init__.py文件
  2. # -*- coding: UTF-8 -*-
  3. #blog:http://www.cnblogs.com/linux-chenyang/
  4. print('--------------api package------')
  5. __all__=['versions','policy']
  6.  
  7. #包的导入文件,和glance同级
  8. #运行from import *就是代表运行api包下的__init__.py的文件
  9. #若想要运行api下的其他模块,在api下的__init__.py用__all__ = []来指定
  10. from glance.api import *
  11.  
  12. policy.get()
  13. versions.create_resource('versions函数')
  14.  
  15. #输出
  16. --------------glance package------------
  17. --------------api package------
  18. from policy.py
  19. from version.py: versions函数

4.5 绝对导入和相对导入

  1. #需求1:policy.py文件调用versions.py里的create_resource函数,在glance同级目录下执行
  2.  
  3. #policy文件
  4. def get():
  5. print('from policy.py')
  6.  
  7. from glance.api import versions #要想在最外层调用模块,必须用from import的方式,在当前脚本执行会报错,除非加上环境变量
  8.  
  9. versions.create_resource('这是versions的函数')
  10.  
  11. #glance同级目录下执行
  12. import glance.api.policy
  13. glance.api.policy.get()
  14.  
  15. #输出:
  16. --------------glance package------------
  17. --------------api package------
  18. from version.py: 这是versions的函数
  19. from policy.py
  20.  
  21. #需求2:在glance/api/version.py中想要导入glance/cmd/manage.py,在glance同级目录下执行
  22. #version文件
  23. def create_resource(conf):
  24. print('from version.py: ', conf)
  25.  
  26. #绝对导入
  27. from glance.cmd.manage import main
  28. main()
  29.  
  30. #相对导入
  31. from ..cmd.manage import main #一个.表示上一级目录,两个点表示上上级目录
  32. main()
  33.  
  34. #glance同级目录下执行
  35. import glance.api.versions
  36. glance.api.versions.create_resource('aa')
  37.  
  38. 输出:
  39. --------------glance package------------
  40. --------------api package------
  41. from manage.py
  42. from manage.py
  43. from version.py: aa

总结:from....import...的方法用来导入子包,import的方法用来导入内置的和第三方模块

4.6 单独导入包

  1. #在与glance同级的test.py中
  2. import glance
  3. glance.db.models.register_models('单独导入')
  4.  
  5. '''
  6. 执行结果:
  7. AttributeError: module 'glance' has no attribute 'db'
  8.  
  9. '''
  10.  
  11. #解决方法
  12. #glance/__init__.py
  13. from . import db
  14.  
  15. #glance/db/__init__.py
  16. from . import models
  17.  
  18. #输出结果:
  19. --------------glance package------------
  20. --------------db package------
  21. from models.py: 单独导入

千万别问:__all__不能解决吗,__all__是用于控制from...import * ,fuck

补充:from import的用法

包可以用“from 目录 import 模块名”这种方式来导入,但是目录不行,只能用‘from 模块 import 函数’

Python_oldboy_自动化运维之路_函数,装饰器,模块,包(六)的更多相关文章

  1. Python_oldboy_自动化运维之路_面向对象2(十)

    本节内容: 面向对象程序设计的由来 什么是面向对象的程序设计及为什么要有它 类和对象 继承与派生 多的态与多态性 封装 静态方法和类方法 面向对象的软件开发 反射 类的特殊成员方法 异常处理 1.面向 ...

  2. Python自动化运维之6、函数装饰器

    装饰器: 装饰器可以使函数执行前和执行后分别执行其他的附加功能,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator),装饰器的功能非常强大.装饰器一般接受一个函数对象作为参数, ...

  3. Python_oldboy_自动化运维之路_线程,进程,协程(十一)

    本节内容: 线程 进程 协程 IO多路复用 自定义异步非阻塞的框架 线程和进程的介绍: 举个例子,拿甄嬛传举列线程和进程的关系: 总结:1.工作最小单元是线程,进程说白了就是提供资源的 2.一个应用程 ...

  4. Python_oldboy_自动化运维之路_面向对象(十)

    面向对象编程 OOP编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述,使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向 ...

  5. Python_oldboy_自动化运维之路_全栈考试(七)

    1. 计算100-300之间所有能被3和7整除的所有数之和 # -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ c ...

  6. Python_oldboy_自动化运维之路_全栈考试(五)

    1.执行 Python 脚本的两种方式 [root@localhost tmp]# cat a.py #!/usr/bin/python # -*- coding: UTF-8 -*- print & ...

  7. Python_oldboy_自动化运维之路(八)

    本节内容: 列表生成式,迭代器,生成器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器,生成器 1.列表生成式 #[列表生成] #1.列 ...

  8. Python_oldboy_自动化运维之路_socket编程(十)

    链接:http://www.cnblogs.com/linhaifeng/articles/6129246.html 1.osi七层 引子: 须知一个完整的计算机系统是由硬件.操作系统.应用软件三者组 ...

  9. Python_oldboy_自动化运维之路(四)

    本节内容 集合 字符编码与转码 函数语法及基本特性 函数参数与局部变量 返回值和嵌套函数 递归 匿名函数 高阶函数 1.集合 集合是一个无序的,不重复的数据组合,它的主要作用如下: 去重,把一个列表变 ...

随机推荐

  1. 遇到问题---java---@value注解为null

    Spring 3支持@value注解的方式获取properties文件中的配置值,大简化了读取配置文件的代码. 在xml文件中配置properties文件 例如 cas.authn.mongo.col ...

  2. MVC3控制器方法获取Form数据方法

    http://www.cnblogs.com/bianlan/archive/2013/01/12/2857310.html 控制器方法获取View页面传送的数据有多种方法,以Edit方法为例: 1. ...

  3. 网络中,FIFO、LRU、OPT这三种置换算法的缺页次数

    FIFO.LRU.OPT这三种置换算法的缺页次数 转载  由于要考计算机四级网络,这里遇到了问题,就搜了一些资料来解疑. 考虑下述页面走向: 1,2,3,4,2,1,5,6,2,1,2,3,7,6,3 ...

  4. 【题解】【THUSC 2016】成绩单 LOJ 2292 区间dp

    Prelude 快THUWC了,所以补一下以前的题. 真的是一道神题啊,网上的题解没几篇,而且还都看不懂,我做了一天才做出来. 传送到LOJ:(>人<:) Solution 直接切入正题. ...

  5. ural 2032 Conspiracy Theory and Rebranding (数学水题)

    ural 2032  Conspiracy Theory and Rebranding 链接:http://acm.timus.ru/problem.aspx?space=1&num=2032 ...

  6. git更换 拉取推送地址

    更换:git remote set-url originhttp://git.caomall.cn/sucry/mouse.git」

  7. GO_01:Mac之Go语言Idea环境配置

    声明:本人所使用的是Mac Pro 安装开始 1. 首先将 GO 基础组件安装好,就好似 java 中的 jdk.当然,安装的时候需要到官网去下载,这一步难倒了好多无法FQ的同学们,故这里我将我这边下 ...

  8. LeetCode-330.Patching Array

    /** * nums的所有元素,假设最大能连续形成[1,sum] 当增加一个element的时候 * 会变成 [1,sum] [element+1,sum+element]两个区间,这两个区间有以下可 ...

  9. bzoj千题计划151:bzoj1131: [POI2008]Sta

    http://www.lydsy.com/JudgeOnline/problem.php?id=1131 dp[i]=dp[fa[i]]-son[i]+n-son[i] #include<cst ...

  10. COGS 513 八

    513. 八 http://www.cogs.pro/cogs/problem/problem.php?pid=513 ★☆   输入文件:eight.in   输出文件:eight.out   简单 ...