美文网首页
高级语法

高级语法

作者: 赵佳辰 | 来源:发表于2017-08-09 00:02 被阅读0次

    高阶函数:以其他函数作为其参数或者返回值的函数。跟JS一样,python提供了部分内置高阶函数

      # 分解和汇总:map/reduce,作为内置高阶函数应用于python
      #  map:将一个集合中所有的元素经过指定函数处理之后组成一个新集合
      #  [f(1), f(2), f(3), f(4), f(5)]
      def f1(x): return x*x
      print map(f1, [1, 2, 3, 4, 5])
      #  输出:[1, 4, 9, 16, 25]
    
      #  reduce:从集合头开始取两个元素交给指定函数计算出一个返回值,
      #  再与下个元素组合成两个元素继续计算合并
      #  f(f(f(f(1, 2), 3), 4), 5)
      def f2(x, y):  return x + y
      print reduce(f2, [1, 2, 3, 4, 5])
      #  输出:15
    
      #  filter:从集合中筛选出能够符合指定函数的元素集合
      #  [f(1) ? 1 : None, f(2) ? 2 : None, f(3) ? 3 : None]
      def f3(x): return x%2 == 0
      print filter(f3, [1, 2, 3, 4, 5])
      #  输出:[2, 4]
    
      #  sorted:对集合按指定的函数进行排序,函数接受两个元素进行比较,
      #  former < back则返回-1,former == back则返回0,former > back则返回1。
      #  如果不给出比较函数,则按照如上比较策略排序
      def f4(f, b):
        if(f < b):  return 1
        elif(f == b): return 0
        elif(f > b):  return -1
      print sorted([4, 3, 5, 1, 2])
      print sorted(f4, [4, 3, 5, 1, 2])
      #  输出:[1, 2, 3, 4, 5]
      #       [5, 4, 3, 2, 1]
    

    匿名函数:python的匿名函数用关键字lambda描述

      #  lambda [params]: [return]
      lambda x: x*x #相当于:def f(x): return x*x
    

    装饰器模式:python的装饰器模式由装饰器函数实现

      def decorator(func):
        def wrapper(*args, **kw):
          #做一些函数调用之前的工作
          ret = func(*args, **kw)
          #做一些函数调用之后的工作
          return ret
        return wrapper
    
      @decorator
      def f(x, y, z):
        return x + y + z
      #  这样,函数f就会被装饰着decorator所包装
    
      #  这过程当中相当于执行了:f = log(f)的操作,我们定义的f函数变量指向了高阶函数log的返回值
    
      #  配合着函数的__name__属性和系统时间,就可以做一个log装饰器
      import time
      def log(func):
        def wrapper(*args, **kw):
          tTime = time.time()
          print "function %s"%func.__name__,"has been called at %d."%tTime
          ret = func(*args, **kw)
          print "function %s"%func.__name__,"used %d"%(time.time() - tTime),"milliseconds"
          return ret
        return wrapper
    
      @log
      def f(x, y):  return x + y
    
      print f(1, 4)
      #  输出:function f has been called at 1502204876.
      #       function f used 0 seconds
      #       5
    

    偏函数:我的理解是在原有函数的基础上,进行一定的修改(不过事后用高阶函数的方式也轻松搞定了-_-)

      #  廖雪峰的例子
      import functools
      int2 = functools.partial(int, base=2)
      int2('1000000')
    
      #  用高阶函数的实现方式(顺便试了下匿名函数)
      def f(x = 2): return x*x
      f3 = lambda x = 3: f(x)
      print f3()
    

    模块:一个.py文件就是一个模块,为了防止命名冲突,可以吧模块放进不同的包中
    包:一个带有init.py文件的文件夹就是一个包

      root  #root包
        |
        +-- __init__.py
        |
        +-- abc.py  #root.abc模块
        |
        +-- hello  #hello包
              |
              +-- __init__.py
              |
              +-- abc.py  #hello.abc模块
    

    导入模块:用import关键字导入指定的模块

      import module  # module会变成一个变量指向这个模块
      #  如果导入失败,会引发ImportError异常
    
      #  也可以使用as关键字为导入的模块取别名
      import module [as mdl]  # 模块变为指向mdl这个变量
    

    模块组件的作用域:用于指定那些函数、变量对外公开,那些私用

      #   __XXXX__:特殊组件
      #  _XXXX or __XXXX:私有组件
      #  XXXX:公开组件
    

    安装外部包:跟npm一样,只不过用的是pip

      pip install package
      
      #  一旦装好了包便可以通过import的方式引用了,
      #  python查找包的路径是按照sys.path(数组)的定义流程来查找的
      import sys
      print sys.path
      
      #  如果要修改,可以直接修改sys.path数组(临时)
      #  也可以修改环境变量(永久)
      #  (不过一般不会修改吧 -_-)
    

    使用新版特性:引入future模块可以使用最新版的语法
    类和对象:

      #  定义类格式(小括号里面的是类的父类):
      class Test(superClass):
        pass
    
      #  定义构造函数、属性和方法
      class Test(object):
        def __init__(self, id, name):
          self.id = id
          self.name = name
        def printSelf(self):
          print self.id
          print self.name
    
      #  定义实例对象(不需要new关键字)
      a = Test(100, "abcd")
      a.printSelf()
    

    所有python类的方法,第一个参数都是self,即这个类的当前实例

    类成员访问域:只分为私有和公开,私有成员的名字前带双下划线

      class Test(object):
        def __init__(self, id):
          self.__id = id
        def __addId(self):
          self.__id = self.__id + 1
        def printId(self):
          self.__addId()
          print self.__id
    
      Test(10).printId()
    

    继承和多态:多态主要反映在isinstance()函数上,问一个子类对象是不是父类的实例,会返回True
    对象信息函数:

      #  type()函数用于返回类或对象的类型,可以用于比较,python也提供了一个系统包定义了所有内部类型的type对象
      #  相当于typeof
      import types
      print type(123) == type("abc")
      print type(123) == types.IntType
      #  type函数的功能其实很强悍,我们甚至可以使用type函数创建一个类
      Hello = type('Hello', (object,), dict(hello=fn))
      #  接受三个参数:
      #    1、类名
      #    2、父类常列表(因为tuple,所以要加,)
      #    3、属性方法KV表
      #  之后便可以把Hello当一般类来使用了
      h = Hello()
     
      #  isinstance()函数用于判断一个对象是否是指定类的实例
      print isinstance("abcd", str)
    
      #  dir()函数用于遍历一个对象的所有属性和方法
      print dir(0)
      #  配合getattr()、setattr()和hasattr()可以直接操作一个对象
      #  相当于JS的obj[attr]、obj[attr]和attr in obj
    

    在python中,以__XXXX__命名的属性和方法被标识为特殊属性和方法,之前function类的__name__属性就是特殊属性

    动态成员添加:

      #  针对于实例,python有更简单的方法为实例绑定属性和方法
      from types import MethodType
      a = Test(1)
      a.__age = 15
      a.setAge = MethodType(setAge, a, Test)
      
      #  对于不同的实例,添加的属性和方法是不存在的
      b = Test(5)
      b.setAge(12) #  Error
    
      #  如果要对类的所有对象都添加指定属性和方法,可以把上述操作作用在类上
    
      #  如果想要限制类的属性,可以使用__slots__
      class Test(object):
        __slots__ = ("id", "name")
    
      Test().age = 10 #  Error
    

    需要注意的是,slots仅对当前类有效,其子类不受影响(slots属性是属于当前类的)

    高级属性:@property:同装饰器一样,为类的属性(成员变量)添加访问方法和设置方法

      class Student(object):
        def __init__(self, id):
          self.__id = id
          self.__name = ""
        @property
        def id(self):
          return self.__id
        @property
        def name(self):
          return self.__name
        @name.setter
        def name(self, name):
          if len(name) != 0:
            self.__name = name
    

    多重继承:python支持多重继承(不知怎么处理菱形问题?)
    特殊属性和方法:

      #  __str__方法指定了类的打印信息(相当于JS的toString)
      #  __iter__方法返回一个迭代对象,交由for循环调用
      #  __getitem__方法允许通过下标的方式访问对象(相当于C++的重载[]操作符)
      #  __getattr__方法返回指定属性(相当于JS的obj[prop])
      #  __call__方法指定了当我们把对象当做函数一样来调用时,所调用的方法
      std = Student(10)
      std()  #  这样就是在调用std.__call__方法
    

    异常处理:基本的try - except(catch) - finally - raise(throw)
    断言:条件表达式应该是True,否则,后面的代码就会出错。

      assert n != 0, 'n is zero!'
    

    日志记录:import logging 包之后,便可以记录日志了。可以通过设置级别来指定日志的类型

      import logging
      logging.basicConfig(level=logging.INFO)
      ...
      logging.info('n = %d' % n)
      ...
    

    单步调试工具pdb:命令行级别的单步工具

      python -m pdb helloWorld.py
      #  l - 查看完整代码文件
      #  p - 查看变量当前值
      #  n - 单步执行下一句语句
      #  如果需要执行到指定行,需要在代码文件的指定行添加pdb.set_trace()语句(pdb是import的)
    

    可以使用这种方式编写自己的IDE,或者在Sublime上开发调试环境

    单元测试包:import unittest包之后,就可以定义单元测试类了。从unittest.TestCase派生下来,默认以【test】开头的方法会被标识为测试方法,在测试单元运行时自动被执行

    import unittest
    class Animal:
        def __init__(self):
            self.__health = 10
            self.__body = { "body": 1, "head": 1, "hands": 2, "foot": 2 }
        def eat(self, food):
            self.__health  += food
        def printState(self):
            print "Current health",self.__health
        @property
        def health(self):
            return self.__health
        def __getattr__(self, key):
            return self.__body[key]
    
    class TestAnimal(unittest.TestCase):
        def testInit(self):
            a = Animal()
            self.assertEquals(a.health, 10)
        def testPrint(self):
            a = Animal()
            self.assertTrue("printState" in a)
        def testEat(self):
            a = Animal()
            with self.assertRaises(KeyError):
                val = a["tail"]
    
        #   在测试方法调用之前执行
        def setUp(self):
            print "Start test"
        #   在测试方法调用之后执行
        def tearDown(self):
            print "Test end"
    
    if __name__ == '__main__':
        unittest.main()
    

    文档测试:可以把测试用的代码写在文档里,然后在命令行运行。编译器会执行文档中的测试代码,并把结果写在文档中,以便之后生成文档的用例。

      #  直接使用廖雪峰的例子了
      class Dict(dict):
        '''
        Simple dict but also support access as x.y style.
    
        >>> d1 = Dict()
        >>> d1['x'] = 100
        >>> d1.x
        100
        >>> d1.y = 200
        >>> d1['y']
        200
        >>> d2 = Dict(a=1, b=2, c='3')
        >>> d2.c
        '3'
        >>> d2['empty']
        Traceback (most recent call last):
            ...
        KeyError: 'empty'
        >>> d2.empty
        Traceback (most recent call last):
            ...
        AttributeError: 'Dict' object has no attribute 'empty'
        '''
        def __init__(self, **kw):
            super(Dict, self).__init__(**kw)
    
        def __getattr__(self, key):
            try:
                return self[key]
            except KeyError:
                raise AttributeError(r"'Dict' object has no attribute '%s'" % key)
    
        def __setattr__(self, key, value):
            self[key] = value
    
      if __name__=='__main__':
        import doctest
        doctest.testmod()
    

    注意到最后两行代码。当模块正常导入时,doctest不会被执行。只有在命令行运行时,才执行doctest。所以,不必担心doctest会在非测试环境下执行。

    相关文章

      网友评论

          本文标题:高级语法

          本文链接:https://www.haomeiwen.com/subject/fqmxrxtx.html