高级语法

高阶函数:以其他函数作为其参数或者返回值的函数。跟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会在非测试环境下执行。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,913评论 25 707
  • 要点: 函数式编程:注意不是“函数编程”,多了一个“式” 模块:如何使用模块 面向对象编程:面向对象的概念、属性、...
    victorsungo阅读 1,485评论 0 6
  • 主要总结一些平时遇到的疑难点,在此总结出来,持续更新。可能有些误导大家的地方,欢迎指正。 难点 get,set,w...
    Jimmy木阅读 2,569评论 1 10
  • 朋友圈集合了多样的生活,看了总会有些感触。 恰好那天也是我的爱人生日,那对夫妻在一起10年了,他的爱人勇敢的在朋友...
    漠漠轻寒7阅读 198评论 0 0
  • 一个人最悲哀的是不是不敢面对自己的内心,不敢正视自己的懦弱。不喜欢被忽视,也不喜欢被别人注意,一个矛盾的存在,总是...
    别问我谁是豆芽阅读 94评论 0 0