zoukankan      html  css  js  c++  java
  • Python菜鸟之路:Python基础(二)

    一、温故而知新

    1. 变量命名方式

    旧的方式:

    1 username = 'xxxx'
    2 password = 'oooo'
    View Code

    新的方式:

    1 username, password = 'xxxx', 'oooo'
    View Code

     2. Python中如何定义常量

      常量:指一旦初始化之后就无法修改的固定值。

      Python中实际是没有这样的名称去定义一个常量的。但是通常变量名是全部大写的话,表示一个常量。比如:MYSQL_CONNECTION。

      同时,《Python Cookbook》一书中提供了定义常量模块const,此类是定义了一个方法__setattr__()和一个异常类型ConstError,主要是判断定义的常量是否在字典中,在则抛出异常,否则,给新创建的常量赋值。代码如下:

    1 class _const:
    2     class ConstError(TypeError):pass
    3     def __setattr__(self,name,value):
    4         if self.__dict__.has_key(name):
    5             raise self.ConstError,"Can't rebind const (%s)"% name
    6         self.__dict__[name]=value
    7 
    8 import sys
    9 sys.modules[__name__]=_const()
    View Code

      经测试python2中可以运行,且报出异常const.ConstError: can't rebind const(magic) 

    3. pyc文件和__pycache__是怎么回事?And pyo ?

    3.1 pyc 文件

      pyc 是由py文件经过编译后二进制文件(也叫字节码文件),py文件变成pyc文件后,加载的速度有所提高,而且pyc是一种跨平台的字节码,是由python 的虚拟机来执行的。pyc的内容,是跟python的版本相关的,不同版本编译后的pyc文件是不同的。

      官方还有这样一段解释如下:

      A program doesn't run any faster when it is read from a ‘.pyc’ or ‘.pyo’ file than when it is read from a ‘.py’ file; the only thing that's faster about ‘.pyc’ or ‘.pyo’files is the speed with which they are loaded.
      When a script is run by giving its name on the command line, the bytecode for the script is never written to a ‘.pyc’ or ‘.pyo’ file. Thus, the startup time of a script may be reduced by moving most of its code to a module and having a small bootstrap script that imports that module. It is also possible to name a ‘.pyc’ or ‘.pyo’file directly on the command line.

    如何手动生成:

      python2.7版本中,通过如下方式可以生成:(Python3.5测试失败)

    1 Python 2.7.11 (v2.7.11:6d1b6a68f775, Dec 5 2015, 20:40:30) [MSC v.1500 64 bit (
    AMD64)] on win32
     Type "help", "copyright", "credits" or "license" for more information.
    2 >>> import py_compile
    3 >>> py_compile.compile("b.py")
    4 >>> exit()

      另外一种方式则是在其他python文件中import 该文件,无论2.7还是3.5都是可以生成的。

    3.2 __pycache__

      为了提高模块加载的速度,每个模块都会在__pycache__文件夹中放置该模块的预编译模块,命名为module.version.pyc,version是模块的预编译版本编码,一般都包含Python的版本号。例如在CPython 发行版3.5中,shopping.py文件的预编译文件就是:__pycache__/shopping.cpython-35.pyc。这种命名规则可以保证不同版本的模块和不同版本的python编译器的预编译模块可以共存。运行的当前脚本(__main__)不会生成pycache,被import的那些modules才会.

      脚本在运行之前会首先检查python文件的最后编辑日期和预编译模块的编译时间,从而决定是否需要重新编译。预编译模块也是跨平台的,所以不同的模块是可以在不同的系统和不同的架构之间共享的。Python在两种情况下不检查缓存。第一种,从命令行中直接加载的模块总是会重新编译并且结果不保存。第二种,如果没有源模块,则不会检查缓存。为了支持无源代码的部署方式,应该将预编译模块放在源代码文件夹中而不是__pycache__中,并且不要包含源代码模块

    3.3 pyo ??? 

      pyo文件,是python编译优化后的字节码文件。pyo文件在大小上,一般小于等于pyc文件。如果想得到某个py文件的pyo文件,可以这样:
      python -O -m py_compile xxxx.py。

      参数说明:使用-O和-OO参数来降低预编译模块的大小。-O开关会去除assert语句,-OO开关会去除assert语句和__doc__字符串。因为有些模块要依赖这些语句,因此只有当你确认模块的内容时才去使用这些开关。优化模块的后缀名是.pyo。

      .pyo和.pyc文件的执行速度不会比.py文件快,快的地方在于模块加载的速度。

      compileall模块可以用来把某个文件夹的中的所有文件都编译成为.pyc或者.pyo文件。

    官方的一段解释:

      When the Python interpreter is invoked with the -O flag, optimized code is generated and stored in .pyo files. The optimizer currently doesn’t help much; it only removes assert statements. When -O is used, all bytecode is optimized; .pyc files are ignored and .py files are compiled to optimized bytecode.
      A program doesn’t run any faster when it is read from a .pyc or .pyo file than when it is read from a .py file; the only thing that’s faster about .pyc or .pyo files is the speed with which they are loaded.

    贴一个其他网站的对比图:

      

     4. Python3 与Python2的另外一点区别

      详情看下边的输出:

    Python 3.5.1 (v3.5.1:37a07cee5969, Dec  6 2015, 01:54:25) [MSC v.1900 64 bit (AM
    D64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> a=12837912739817983719379179321
    >>> type(a)
    <class 'int'>
    >>> exit()
    
    
    Python 2.7.11 (v2.7.11:6d1b6a68f775, Dec  5 2015, 20:40:30) [MSC v.1500 64 bit (
    AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> a=12837912739817983719379179321
    >>> type(a)
    <type 'long'>

      从上边可以看出,python3中,int和long统一整合为“int”型。

    5. is和 == 的区别

      is检查两个对象是否是同一个对象(同一性),类似C语言中的指针。判断同一性,可以用id来查看下在内存的地址空间。。(obj1 is obj2) 等价于 (id(obj1) == id(obj2))

      ==检查他们是否相等(等值性)。

    异常现象:

    python2中如果比较float型数字, 比如a,b = 2.5,2.5 那么id(a) != id(b)

    python3中如果比较float型数字, 比如a,b = 2.5,2.5 那么id(a) == id(b) 

      上述的变化,或许是python3的一些优化,具体原因我还不知道,后续如果有学习到,会进行更新。

    6. 字符串拼接符 “+” 、join 和 "%s"占位符的区别#这里的说法不一定正确,等待以后能力达到了, 自己去研究底层实现的区别

      “+”是copy内存复制,所以每次“+”都需要进行内存拷贝,而join是一次性拷贝。

      “%s”也是在定义变量的时候,提前划分一块内存空间出来。

      当然了,不妨试试str.format()

    二、新知识整理

    1. 列表

      python3中,新增copy和clear方法,代码如下

    1     def clear(self): # real signature unknown; restored from __doc__
    2         """ L.clear() -> None -- remove all items from L """
    3         pass
    4 
    5     def copy(self): # real signature unknown; restored from __doc__
    6         """ L.copy() -> list -- a shallow copy of L """
    7         return []
    View Code

    2.7与3.5的另一个差异:
      2.7中,可以直接对列表进行排序,list.sort() ,列表中可以存在数字和字符串。
      3.0中,会提示错误: TypeError: unorderable types: str() < int()。详情看下面代码:

    1 >>> a=['b',2]
    2 >>> a.sort()
    3 Traceback (most recent call last):
    4   File "/work/shopping.py", line 7, in <module>
    5     a.sort()
    6 TypeError: unorderable types: int() < str()
    View Code

    2. 字典

       python3 中去除了Python2 dict的has_key 、iteritems 、 itervalues 、 iterkeys、viewvalues 等方法。具体原因不知道...但是感觉少了迭代器,麻烦了很多。有迭代器,各种遍历不得不说会效率高很多……If you want to return an iterator in Python3.x, use iter(dictview) :

     1 >>> d = {'one':'1', 'two':'2'}
     2 >>> type(d.items())
     3 <class 'dict_items'>
     4 >>>
     5 >>> type(d.keys())
     6 <class 'dict_keys'>
     7 >>>
     8 >>>
     9 >>> ii = iter(d.items())
    10 >>> type(ii)
    11 <class 'dict_itemiterator'>
    12 >>>
    13 >>> ik = iter(d.keys())
    14 >>> type(ik)
    15 <class 'dict_keyiterator'>
    View Code

      另外,随机的一些方法尽量少用:例如   dict.iterms() dict.values() dict.fromkeys() dict.popiterms()

    3. 元组

      tuple在python2/3中,无明显差异,具体不再说明。

    4. 字符串

      对于字符串,我一般是按照字符串=list的方式来记忆以及使用的。虽然不具备list的诸多方法,但是还是有很多共通处的。下面介绍string的几个非常好用的方法。

    4.1 string.format(*args, **kwargs)

      .format方法用来格式化输出字符串。与%s占位符是一样的。

    >>> name='My name is {name} ,age is {age}'
    >>> name.format(name='Bob',age=33)
    或
    >>> name='My name is {0} ,age is {1}'
    >>> name.format(name='Bob',age=33)
    
    输出:
    >>> My name is Bob ,age is 33

    4.2 string.center(width, fillchar=None)

      .center方法返回指定长度的字符串,不足用fillchar来进行两侧填充。

    1 >>> name = 'Home Work Is Hard'
    2 >>> print(name.center(40,'#'))
    3 输出:
    4 ###########Home Work Is Hard############
    View Code

     5. 补充collections模块

      Python的collections模块在这些内置数据类型的基础上,提供了几个额外的数据类型:namedtuple, defaultdict, deque, Counter, OrderedDict等,其中namedtuple和OrderDic是两个很实用的扩展类型。(写博客我认为最忌讳的就是洋洋洒洒一大堆,自己记忆麻烦,别人看着累赘,没有突出点)

    5.1 namedtuple命名元组

         namedtuple是一个函数,它用来创建一个自定义的tuple对象,并且规定了tuple元素的个数,并可以用属性而不是索引来引用tuple的某个元素。

    eg : 如果要用坐标和半径表示一个圆,可以用namedtuple定义:

     1 from collections import *
     2 Yuan = namedtuple('circle',['x','y','z'])
     3 #或者Yuan = nametuple('circle','x y z')
     4 yuan = Yuan(1,2,3)
     5 print(yuan.x)
     6 print(yuan.y)
     7 print(yuan.z)
     8 输出:
     9 1
    10 2
    11 3
    View Code

      再来一个更加贴近实际的例子

    from collections import namedtuple
      
    # 变量名和namedtuple中的第一个参数一般保持一致,但也可以不一样
    Student = namedtuple('Student', 'id name score')
    # 或者 Student = namedtuple('Student', ['id', 'name', 'score'])
      
    students = [(1, 'Wu', 90), (2, 'Xing', 89), (3, 'Yuan', 98), (4, 'Wang', 95)]
      
    for s in students:
      stu = Student._make(s)
      print stu
    
    #def _make(cls, iterable, new=tuple.__new__, len=len):
    #       'Make a new named tuple object from a sequence or #iterable.'
    #       return new(cls, iterable) 
    
    # Output:
    # Student(id=1, name='Wu', score=90)
    # Student(id=2, name='Xing', score=89)
    # Student(id=3, name='Yuan', score=98)
    # Student(id=4, name='Wang', score=95)
    View Code

    5.2 OrderDic有序字典

      使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。如果要保持Key的顺序,可以用OrderedDict

    1 >>> from collections import OrderedDict
    2 >>> d = dict([('a', 1), ('b', 2), ('c', 3)])
    3 >>> d # dict的Key是无序的
    4 {'a': 1, 'c': 3, 'b': 2}
    5 >>> od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
    6 >>> od # OrderedDict的Key是有序的
    7 OrderedDict([('a', 1), ('b', 2), ('c', 3)])
    View Code

    注意,OrderedDict的Key会按照插入的顺序排列,不是Key本身排序:

    1 >>> od = OrderedDict()
    2 >>> od['z'] = 1
    3 >>> od['y'] = 2
    4 >>> od['x'] = 3
    5 >>> list(od.keys()) # 按照插入的Key的顺序返回
    6 ['z', 'y', 'x']
    View Code

    5.3 deque双向队列

      本质上就是一个列表……只是增加了一些双向操作的方法。这里不再多描述。

    今天的整理总结就到这儿,希望看完之后大家能有不同的收获。

  • 相关阅读:
    I/O 请求数据包
    设备节点和设备堆栈
    观察者模式,即发布-订阅模式
    建造者模式,即生成器模式
    外观模式,即门面模式
    迪米特法则(LoD),即最少知识原则
    模板方法模式
    原型模式
    工厂方法模式
    代理模式
  • 原文地址:https://www.cnblogs.com/jishuweiwang/p/5497804.html
Copyright © 2011-2022 走看看