Python学习第二阶段day1 内置函数,序列化,软件目录开发规范

内置函数

 

1.abs()  求绝对值

2.all()    所有元素为真才返回真 all( [1,1,2,3,-1] ) 值为True  

3.any()   所有元素为假才返回假  any([0,0,0,0,0])  值为FALSE  

4.ascii()  返回括号内对象的唯一ASCII表现形式,好像没什么卵用

5.bin()    括号内Int型的十进制转换为二进制

6.hex()  括号内十进制转十六进制       6.oct()  括号内十进制转八进制       6.bool()   判断括号内表达式的真假

7.bytearray()   可以改变值的byte类型,str?很少用

str = "abcde"
barray = bytearray(str, encoding="utf8")
print(barray[0])     # 输出97
barray[0] = 100
print(barray)       # 输出bytearray(b'dbcde')

8.bytes()  字符串变为bytes类型

print(bytes(str,encoding="gbk"))  # 输出b'abcde'

 9.callable()  判断括号内的函数是否能被调用

10. chr()   括号内输入ASCII码,返回字符   10 ord()  括号内输入字符,返回Unicode码

11.  classmethod()   ..................

12.compile()   把代码编译成字节码例如,compile('print (2)', '',  'exec')  得到一个内存地址

13.complex()   转换复数的,估计用不到了

14.delattr()   删除某对象的某属性

15. dict()     dict({'1':1,'2':2})  = {'1':1,'2':2}    dict()  = {}

16.dir()     查看括号内对象的所有方法

17.divmod()  返回商和余数 divmod(5,2) = (2,1)

18. enumerate()  遍历用的

19.eval()  将字符串str当成有效的表达式来求值并返回计算结果。或者把字符串转换成对应的格式。所以,结合math当成一个计算器很好用

      eval("5**2") = 25   eval("[1,2,3,4,5]") = [1,2,3,4,5]   

20.exec()  执行代码段,eval()函数只能计算单个表达式的值,而exec()函数可以动态运行代码段。exec(object[, globals[, locals]])  其中object为字符串或code对象。globals[, locals为可选参数。例如:

x = 10
expr = """
z = 30
sum = x + y + z
print(sum)
"""
def func():
    y = 20
    exec(expr)          #  输出60
    exec(expr, {'x': 1, 'y': 2})   #  输出33
    exec(expr, {'x': 1, 'y': 2}, {'y': 3, 'z': 4})   # 输出34
func()
--------------------------------------------------最后一个相当于---------
x = 1
y = 2
def func():
  y = 3
  z = 4
  z = 30
  sum = x + y + z
  print(sum)
func()

21.filter()    包括两个参数,分别是function和list。该函数根据function参数返回的结果是否为真来过滤list参数中的项,最后返回一个新列表

def sayhi(n):

  print(n)

可以用匿名函数代替,calc = lambda n:print(n)  传参:calc(5) 或 (lambda n:print(n))(5)   如果sayhi里有for循环就不能用匿名函数了,匿名函数里最多只能写三元运算符calc = lambda n:3 if n<4 else n单独用lambda的情况不多,而是跟filter()结合起来使用,在一组数据中过滤出你想要的:

res = filter(lambda n:n>5,  range(10))

for i in res:

  print(i)               打印结果  6 7 8 9

22. map()   两个参数一个是函数名,另一个是列表或元组,   对列表或元祖的每个值按lambda的方法处理

res = map(lambda n:n*n , range(10))

for i in res:

  print(i)                 打印结果0 1 4 9 16 25 36 49 64 81 

或者[i*i  for  i  in range(10)]     或者  [lambda i : i*i  for i in range(10)]

23.  reduce()   按照给定的方法把输入参数中上序列缩减为单个的值。例如

reduce(lambda x,y:x*y, [1,2,3,4,5]      # 输出120 ((((1*2)*3)*4)*5

reduce(lambda x,y:x*y, [1,2,3], 10)    #输出60  ((1*2)*3)*10

 24 float()   强制转换float

25 format()  打印输出的时候"{0}, {1}".format(name,age)

26.frozenset()     frozenset([1,2,3,4])不可改变集合,与元祖差不多

27.getattr()    .............

28  globals()  返回整个程序的变量名和变量值,全局的变量,字典的形式

29 locals()   以字典的形式返回局部变量名和值

查找变量顺序: 局部名字空间(函数)-----全局名字空间(模块)------内置名字空间

30 hasattr()  ...........

31 hash() 哈希表示某种不变的映射关系,用某种hash算法,每个输入对应唯一一个输出,只要输入不变,不论运行多少次,输出都不会变。对某集合内的元素使用哈希映射得到的值进行排序可以加快查找速度。

32 help()  可以交互式的查询帮助信息

33. id()   返回对象的标识,保证同时存在的对象之间是唯一的,当前使用的内存地址做标识

34  input() 输入

35 int()  强制转换为int

36  isinstance()   判断是可迭代对象还是迭代器。判断是不是某个类的实例

37  issubclass ...

38   iter()     括号内可迭代对象转换为迭代器

39   len()   长度

40   list()    list初始化

50    max()  求最大值

51    min()  求最小值

52    memeryview()  本函数是返回对象obj的内存查看对象。所谓内存查看对象,就是对象符合缓冲区协议的对象,为了给别的代码使用缓冲区里的数据,而不必拷贝,就可以直接使用。

53  next()   生成器的next() 方法

54  object()  .........

55  open()  打开文件获得文件操作句柄

56 pow()  求幂运算,pow(3,2) 返回3² = 9

57  print()  输出

58  property() .................

59  range()   迭代器

60  repr()        返回对象的string描述      For many object types, including most builtins, eval(repr(obj)) == obj.

61  reversed()    反转reverse iterator over values of the sequence    Return a reverse iterator

62  round()      round(1.3342   ,2)  == 1.33

63  set()       集合初始化

64   setattr()  ............

65  slice()  Create a slice object. This is used for extended slicing (e.g. a[0:10:2])

66  sorted()  排序,按key排序 print(sorted(a))  a是字典,  按value排序  print(sorted(a.items())) 

Return a new list containing all items from the iterable in ascending order.

A custom key function can be supplied to customize the sort order, and the
reverse flag can be set to request the result in descending order.

67 staticmethod()  .....

68  str()  强转字符串

69   sum()  求和

70   super()  ....

71   tuple()  将seq转为元祖,tuple(seq)

72   type()   查看括号内对象的类型

73   vars()  

vars([object]) -> dictionary

Without arguments, equivalent to locals().
With an argument, equivalent to object.__dict__.

74   zip() 拉链

a=[1,2,3,4]  b=['a','b','c','d']

print(zip(a,b))    打印 [(1,a),(2,b),(3,c),(4,d)]

75   __import__()

 序列化json pickle

序列化:seriazable

import json
# json只能处理简单的数据类型,用于不同语言间的数据交互
info = {
    'name': 'alex',
    'age': 23
}
with open("seriaze",'w',encoding="utf8") as f:
    json.dump(info, f)
    #f.write(json.dumps(info))


# 处理复杂的怎么办呢?pickle只能在本语言用
import pickle
def sayhi():
    print("hello")
info1 = {
    'name': 'alex',
    'age': 23,
    'func': sayhi
}
with open('seriaze1','wb') as f:
    pickle.dump(info1, f)
View Code

反序列化:deseriazable

# json反序列化
import json

with open("seriaze","r") as f:
    data = json.load(f)
    #data = json.loads(f.read())
for k in data:
    print(k, data[k])

# pickle反序列化,内存地址找不到了,sayhi随程序结束释放了
import pickle
def sayhi():
    print("hellooo111")
with open("seriaze1", 'rb') as f:
    data = pickle.load(f)
print(data['func']()) #  打印hellooo111
View Code

 把对象存到文件中的过程称为序列化,文件中只能保存字符串或者二进制

读取文件得到对象称为反序列化

Python3.x中序列化可以进行多次,而反序列化只能一次。因此建议一次序列化,和一次反序列化。存最新文件冲掉

 软件目录规范

 参考:http://www.cnblogs.com/alex3714/articles/5765046.html

假设你的项目名为foo, 我比较建议的最方便快捷目录结构这样就足够了:

Foo/
|-- bin/
|   |-- foo
| |-- conf/ 配置文件目录
| |-- foo/主程序目录,主要的程序逻辑 | |-- tests/测试用例 | | |-- __init__.py | | |-- test_main.py | |.......主程序逻辑,代码文件 | |-- __init__.py 有这个文件叫包,创建包之后就有一个空的init | |-- main.py 程序主入口,从foo去调用main | |-- docs/文档 | |-- conf.py | |-- abc.rst | |-- setup.py 安装的脚本 |-- requirements.txt程序依赖关系,例如mysql,等 |-- README

------------------------------动态获取绝对路径加到环境变量

__file__: 相对路径

os.path.abspath(__file__): 绝对路径 atm.py

os.path.dirname(   os.path.abspath(__file__)   ) :  返回目录名,不要文件名bin

BASE_DIR = os.path.dirname(  os.path.dirname(  os.path.abspath(__file__)  )   ) :  再上一级Atm

sys.path.append( BASE_DIR )   添加环境变量

--------------------------

import  conf,atm

atm.main 无法执行用下一种方法

------------------------

from  conf  import  setting

from  atm  import   main

main.loggin()

--------------------------

简要解释一下:

  1. bin/: 存放项目的一些可执行文件,当然你可以起名script/之类的也行。
  2. foo/: 存放项目的所有源代码。(1) 源代码中的所有模块、包都应该放在此目录。不要置于顶层目录。(2) 其子目录tests/存放单元测试代码; (3) 程序的入口最好命名为main.py
  3. docs/: 存放一些文档。
  4. setup.py: 安装、部署、打包的脚本。
  5. requirements.txt: 存放软件依赖的外部Python包列表。
  6. README: 项目说明文件。

除此之外,有一些方案给出了更加多的内容。比如LICENSE.txt,ChangeLog.txt文件等,我没有列在这里,因为这些东西主要是项目开源的时候需要用到。如果你想写一个开源软件,目录该如何组织,可以参考这篇文章

下面,再简单讲一下我对这些目录的理解和个人要求吧。

关于README的内容

这个我觉得是每个项目都应该有的一个文件,目的是能简要描述该项目的信息,让读者快速了解这个项目。

它需要说明以下几个事项:

  1. 软件定位,软件的基本功能。
  2. 运行代码的方法: 安装环境、启动命令等。
  3. 简要的使用说明。
  4. 代码目录结构说明,更详细点可以说明软件的基本原理。
  5. 常见问题说明。

我觉得有以上几点是比较好的一个README。在软件开发初期,由于开发过程中以上内容可能不明确或者发生变化,并不是一定要在一开始就将所有信息都补全。但是在项目完结的时候,是需要撰写这样的一个文档的。

可以参考Redis源码中Readme的写法,这里面简洁但是清晰的描述了Redis功能和源码结构。

关于requirements.txt和setup.py

setup.py

一般来说,用setup.py来管理代码的打包、安装、部署问题。业界标准的写法是用Python流行的打包工具setuptools来管理这些事情。这种方式普遍应用于开源项目中。不过这里的核心思想不是用标准化的工具来解决这些问题,而是说,一个项目一定要有一个安装部署工具,能快速便捷的在一台新机器上将环境装好、代码部署好和将程序运行起来。

这个我是踩过坑的。

我刚开始接触Python写项目的时候,安装环境、部署代码、运行程序这个过程全是手动完成,遇到过以下问题:

  1. 安装环境时经常忘了最近又添加了一个新的Python包,结果一到线上运行,程序就出错了。
  2. Python包的版本依赖问题,有时候我们程序中使用的是一个版本的Python包,但是官方的已经是最新的包了,通过手动安装就可能装错了。
  3. 如果依赖的包很多的话,一个一个安装这些依赖是很费时的事情。
  4. 新同学开始写项目的时候,将程序跑起来非常麻烦,因为可能经常忘了要怎么安装各种依赖。

setup.py可以将这些事情自动化起来,提高效率、减少出错的概率。"复杂的东西自动化,能自动化的东西一定要自动化。"是一个非常好的习惯。

setuptools的文档比较庞大,刚接触的话,可能不太好找到切入点。学习技术的方式就是看他人是怎么用的,可以参考一下Python的一个Web框架,flask是如何写的: setup.py

当然,简单点自己写个安装脚本(deploy.sh)替代setup.py也未尝不可。

requirements.txt

这个文件存在的目的是:

  1. 方便开发者维护软件的包依赖。将开发过程中新增的包添加进这个列表中,避免在setup.py安装依赖时漏掉软件包。
  2. 方便读者明确项目使用了哪些Python包。

这个文件的格式是每一行包含一个包依赖的说明,通常是flask>=0.10这种格式,要求是这个格式能被pip识别,这样就可以简单的通过 pip install -r requirements.txt来把所有Python包依赖都装好了。具体格式说明: 点这里

 

关于配置文件的使用方法

注意,在上面的目录结构中,没有将conf.py放在源码目录下,而是放在docs/目录下。

很多项目对配置文件的使用做法是:

  1. 配置文件写在一个或多个python文件中,比如此处的conf.py。
  2. 项目中哪个模块用到这个配置文件就直接通过import conf这种形式来在代码中使用配置。

这种做法我不太赞同:

  1. 这让单元测试变得困难(因为模块内部依赖了外部配置)
  2. 另一方面配置文件作为用户控制程序的接口,应当可以由用户自由指定该文件的路径。
  3. 程序组件可复用性太差,因为这种贯穿所有模块的代码硬编码方式,使得大部分模块都依赖conf.py这个文件。

所以,我认为配置的使用,更好的方式是,

  1. 模块的配置都是可以灵活配置的,不受外部配置文件的影响。
  2. 程序的配置也是可以灵活控制的。

能够佐证这个思想的是,用过nginx和mysql的同学都知道,nginx、mysql这些程序都可以自由的指定用户配置。

所以,不应当在代码中直接import conf来使用配置文件。上面目录结构中的conf.py,是给出的一个配置样例,不是在写死在程序中直接引用的配置文件。可以通过给main.py启动参数指定配置路径的方式来让程序读取配置内容。当然,这里的conf.py你可以换个类似的名字,比如settings.py。或者你也可以使用其他格式的内容来编写配置文件,比如settings.yaml之类的。




posted @ 2017-07-19 12:49  _revolution  阅读(261)  评论(0编辑  收藏  举报