设为首页 收藏本站
查看: 754|回复: 0

[经验分享] Python学习笔记 === python自省

[复制链接]

尚未签到

发表于 2015-4-21 13:03:17 | 显示全部楼层 |阅读模式

  • 示例代码:


    from types import BuiltinFunctionType, BuiltinMethodType, \
    FunctionType, MethodType, ClassType
    def help(object, spacing=10, collapse=1):
    """Print method and doc string.
    Takes module, class, list, dictionary, or string."""
    typeList = (BuiltinFunctionType, BuiltinMethodType, FunctionType. MethodType, ClassType)
    methodList = [method for method in dir(object) if type(getattr(object, method)) in typeList]
    processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s:s)
    print "\n".join(["%s %s" % (method.ljust(spacing), processFunc(str(getattr(object, method).__doc__))) for method i    n methodList])
    if __name__ == "__main__":
    print help.__doc__
  • 自省综述:根据上边示例代码分析

    • 这个模块有一个函数,help, 有三个参数object, spacing, collapse, 后两个是可选参数
    • 函数的代码是缩排的,help函数有一个多行的文档字符串,并没有返回值,因为函数只使用他的效果并非它的值
    • __name__技巧只是用于测试模块,在别的程序引入这个模块的时候不会引起冲突,
    • help函数的设计是为了在ide环境下是用的,接受任何拥有函数或者方法的对象,打印出对象所有的函数和文档字符串
    • 用法举例


      >>> from apihelper import help
      >>> li = []
      >>> help(li)
      append     L.append(object) -- append object to end
      count      L.count(value) -> integer -- return number of occurrences of value
      extend     L.extend(list) -- extend list by appending list elements
      index      L.index(value) -> integer -- return index of first occurrence of value
      insert     L.insert(index, object) -- insert object before index
      pop        L.pop([index]) -> item -- remove and return item at index (default last)
      remove     L.remove(value) -- remove first occurrence of value
      reverse    L.reverse() -- reverse *IN PLACE*
      sort       L.sort([cmpfunc]) -- sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1
    • 高级用法:注意参数变化


      >>> import odbchelper
      >>> help(odbchelper)
      buildConnectionString Build a connection string from a dictionary Returns string.
      >>> help(odbchelper, 30)
      buildConnectionString          Build a connection string from a dictionary Returns string.
      >>> help(odbchelper, 30, 0)
      buildConnectionString          Build a connection string from a dictionary
      Returns string.


  • 导入模块:两种导入模块的方法

    • 基本的from module import 语法


      from types import BuiltinFunctionType, BuiltinMethodType, FunctionType, MethodType, ClassType
        注意:与module导入方法类似,但是,导入模块types的属性和方法被直接导入到局部名字空间中,使用的时候不用模块的名字来限定;

    • import 和 from module import 对比


      >>> import types        #只是有每个对象类型的属性
      >>> types.FunctionType  #必须用module 名称来限定

      >>> FunctionType  #没有定义在当前的名字空间中,只是存在与types的上下问环境当中
      Traceback (most recent call last):
      File "", line 1, in
      NameError: name 'FunctionType' is not defined
      >>> from types import FunctionType
      >>> FunctionType

    • 什么时候要用from module import

      • 如果想经常存取模块的属性和方法,但是不想一遍遍的敲入模块名称
      • 想选择性的导入某些属性和方法,不想要其他的
      • 如果模块包含的属性或者方法和你自己的某个模块名字相同,只能用import module




  • 可选和定名参数(指定参数名字):

    • help的合法调用


      help(odbchelper)                       
      help(odbchelper, 12)                 
      help(odbchelper, collapse=0)    #spacing 缺省      
      help(spacing=15, object=odbchelper) #object可以定名,任意顺序都行


  • type,str,dir和其他内置函数:

    • type:返回任意对象的数据类型


      >>> type("333")

      >>> li=[]
      >>> type(li)

      >>> import odbchelper
      >>> type(odbchelper)

      >>> import types
      >>> type(odbchelper) == types.ModuleType
      True
    • str:强制将数据转换为字符串


      >>> str(1)
      '1'
      >>> ho = ["sd", 1, "sdd"]      #可以工作于任何类型的任何对象
      >>> str(ho)
      "['sd', 1, 'sdd']"
      >>> str(odbchelper) #模块的字符串表示包含了模块在磁盘上的路径
      ""
      >>> str(None)  #python空值 返回字符串 很重要???
      'None'
    • dir:help函数的核心,返回任意一个对象的属性和方法的列表:模块,函数,字符串,列表,字典... 相当多的东西


      >>> li = []
      >>> dir(li)           
      ['append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
      >>> d = {}
      >>> dir(d)            
      ['clear', 'copy', 'get', 'has_key', 'items', 'keys', 'setdefault', 'update', 'values']
      >>> import odbchelper
      >>> dir(odbchelper)     #模块,返回模块中定义的所有东西,包括自定义的
      ['__builtins__', '__doc__', '__file__', '__name__', 'buildConnectionString']
    • 内置属性和函数


      >>> from apihelper import help
      >>> help(__builtins__, 20)
      ArithmeticError      Base class for arithmetic errors.
      AssertionError       Assertion failed.
      AttributeError       Attribute not found.
      EOFError             Read beyond end of file.
      EnvironmentError     Base class for I/O related errors.
      Exception            Common base class for all exceptions.
      FloatingPointError   Floating point operation failed.
      IOError              I/O operation failed.
      [...snip...]
      ???
    • 综合:type dir str, 以及所有其他的python内置函数一样被组合进入一个名字叫做__builtins__的特别模块中,python启动的时候自动from __builtins__ import * 可以直接使用,好处是,可以通过得到builtins的信息,作为一个组,存取所有内置的函数和属性,help函数实现了那个功能。???


  • 使用getattr得到对象的各种引用:可以得到一个直到运行时候才知道的函数的引用???

    • getattr介绍


      >>> li=["larry", "curly"]               
      >>> li.pop              #得到列表的pop方法的一个引用,并不是调用pop方法,而是方法本身

      >>> getattr(li, "pop")   #也返回pop方法的一个引用,但是,方法的名字被指定为一个字符串参数,getattr可以返回任意对象的任意属性,在这个例子中,对象是列表,属性是pop方法

      >>> getattr(li, "append")("moe")  #li.append("moe") 返回值是方法,没有直接调用方法,而是把函数名当作字符串来指定。
      >>> li
      ['larry', 'curly', 'moe']
      >>> getattr({}, "clear")  #也可以用给字典

      >>> getattr((), "pop")     #理论上可以用个序列,但是序列没有方法,所以不管给出什么属性名,getattr都将引发一个异常,
      Traceback (most recent call last):
      File "", line 1, in
      AttributeError: 'tuple' object has no attribute 'pop'
    • 用于apihelper.py, 不仅可以用于内置数据类型,也可以用于模块


      >>> import odbchelper
      >>> odbchelper.buildConnectionString         #返回在odbchelper模块中的bulidConnectionString函数的引用

      >>> getattr(odbchelper, "buildConnectionString") #使用getattr,我们可以得到同一函数的同一引用。 相当于object.attribute. 如果object是一个模块,那么attribute可以是模块中的任何东西:函数,类,或者全局变量。

      >>> object = odbchelper
      >>> method = "buildConnectionString"
      >>> getattr(object, method)  #help函数中用到的东西,method字符串是方法或者函数的名字。

      >>> type(getattr(object, method))  本地方method是一个函数的名字

      >>> import types
      >>> type(getattr(object, method)) == types.FunctionType
      True


  • 过滤列表:python强大的列表映射到其他列表的能力,同一种过滤机制合并,列表中的某个元素被映射,其他的都忽略掉。

    • 列表过滤语法


      [mapping-expression for element in source-list if filter-expression]
        以if开头的就是过滤表达式,可以是任意真假的表达式,任何对于过滤表达式计算出真值的元素将包括在映射中,其他元素忽略掉,他们不会出现在映射表达式中,也不包括在输出列表中。

    • 列表过滤介绍


      >>> li = ["a", "mpilgrim", "foo", "b", "c", "b", "d", "d"]
      >>> [elem for elem in li if len(elem) > 1]         
      ['mpilgrim', 'foo']
      >>> [elem for elem in li if elem != "b"]        # 过滤掉特殊值b,每次b出来过滤表达式都不成立
      ['a', 'mpilgrim', 'foo', 'c', 'd', 'd']
      >>> [elem for elem in li if li.count(elem) == 1] #count返回的是一个元素出现的次数
      ['a', 'mpilgrim', 'foo', 'c']
    • apihelper.py中过滤列表


      typeList = (BuiltinFunctionType, BuiltinMethodType, FunctionType, MethodType, ClassType)
      methodList = [method for method in dir(object) if type(getattr(objec, method)) in typeList]
        看上去挺复杂,但是基本结构是一样的。整个表达式返回一个列表,列表赋给变量methodList,前半部分是列表映射部分,dir(object)返回一个对象的属性和方法的列表,就是正在映射的列表。表达式getattr(object, method)返回一个函数对象,method是模块中的函数名字,这个表达式接受一个object对象,获得它的属性方法,和一些其他东西的名字列表,然后过滤列表,执行过滤通过得到每个属性方法函数的名字,让后通过getattr函数得到指向实际东西的引用。然后用type检查对象类型,我们关心方法和函数,不关心其他属性。classType对象现在不用担心,后边将讨论python的类。



  • and-or技巧:要对比bool?a:b 理解其如何工作


    >>> a = "first"
    >>> b = "second"
    >>> 1 and a or b                   #类似c
    'first'
    >>> 0 and a or b                   #类似c
    'second'
    >>> a = ""
    >>> 1 and a or b                    #区别,看成纯粹的布尔逻辑去分析。
    'second'

    >>> a = ""
    >>> b = "second"
    >>> 1 and a or b
    'second'
    >>> 0 and a or b
    'second'
    >>> (1 and [a] or )[0]  [a] 是一个非空列表 永远为真,
    ''
      Python 中很多时候,不允许使用if语句,一个负责的的程序猿应该将and or 技巧封装成函数:



    def choose(bool, a, b):
    return (bool and [a] or )[0]
      ???

  • 使用lambda函数:快速定义单行的最小函数,可以被用在任何需要函数的地方,函数的语法通常与其他函数有点不同???

    • lambda函数介绍


      >>> def f(x):
      ...     return x*2
      ...
      >>> f(2)
      4
      >>> g = lambda x: x*2  #lambda函数, 没有小括号,return是默认的,函数没有名字。只有将它赋值给变量的变量名g
      >>> g(3)
      6
      >>> (lambda x: x*2)(3)     #可以不赋值给一个变量然后使用它,证明是一个内联函数
      6
        可以接收任意多个参数(包括可选参数)值并且返回单个表达式的值的函数,lambda函数不能包括命令,表达式不能超过一个,不要赛入过多东西。
        lambda函数是风格问题,不一定非要使用,许多小的一行代码不会弄乱我的代码,用在需要特殊封装的,非重用的代码上。

    • 例子中的lambda函数


      processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
        lambda函数在一个布尔环境下总为真,并不意味着不能返回假值,函数本身总是真,返回值可以任何值。

    • split不带参数:上边式子中不带参数


      >>> s = "this   is\na\ttest"  
      >>> print s
      this   is
      a    test
      >>> print s.split() # split不带参数按空白进行分割!!!         
      ['this', 'is', 'a', 'test']
      >>> print " ".join(s.split()) #将空白统一化!!!
      'this is a test'
    • 将函数赋给一个变量


      processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
        processFunc现在是一个函数,但是函数为哪一个要看collapse的值。如果为真processFunc(string)将压缩空白,否则,将返回未改变的参数。

    • 注意:其他不健壮的语言实现它,可能创建一个函数,它接收一个字符串和一个collapse函数,使用一个If语句来判断是否需要压缩空白或者不压缩,然后返回相应的值,但是这样效率比较低,每次调用它,不得不再给出想要的东西之前,判断是否空白。在python中,可以将这种判断逻辑拿到函数之外,定义一个裁剪过的函数lambda来给出确切的(唯一的)你想要的。这样做更有效率更漂亮,并且更少导致那些令人讨厌的错误???


  • 全部放在一起:所有的多米诺骨牌拼接到一起了,然后将它推倒吧。




    • 最后一行的内容





print "\n".join(["%s %s" % (method.ljust(spacing), processFunc(str(getattr(object, method).__doc__))) for method in methodList])



    • 最后一句告诉我们这是一个列表映射,methodLIst是一个在object中所有我们关心的方法的列表。我们用method遍历列表
    • 动态得到文档字符串


      >>> import odbchelper  
      >>> object = odbchelper        #object是我们要得到的帮助的对象                  
      >>> method = 'buildConnectionString'      #method 是当前方法的名字
      >>> getattr(object, method)               #得到在object模块中对于method函数的一个引用

      >>> print getattr(object, method).__doc__   #打印文档字符串
      Build a connection string from a dictionary of parameters.
      Returns string.
      #至于str 是一个 内置函数,强制转换数据,但是不是每个函数都有文档字符串,如果没有的话,__doc__属性是None.
    • 为什么对一个文档字符串使用str


      >>>{}.keys__doc__
      >>>{}.keys__doc__ == None
      1
      >>>str({}.keys__doc__)  #使用str函数就接收了空值,返回它的字符串表示
      None
        然后保证有了字符串,传递字符串给processFunc,这个函数定义了一个要不要压缩空白或者不压缩,因为process假定一个字符串参数,并且调用了split方法,如果传给的是方法None,而不是字符串,函数就会失败了。

    • ljust方法介绍


      >>>s = "build"
      >>>s.ljust(30) #用空格填充到指定长度,这样就可以继续对齐了
      "build        "
      >>>s.ljust(2) #少于字符串的话 返回原字符串
      "build"
    • 打印列表


      >>>li=['a','b']
      >>>print "\n".join(li)   # 一个有用的调试技巧


  11,小结





    • apihelper.py代码和输出


      # 代码
      from types import BiultinFunctionType, BulitinMethodType, FunctionType, MethodType, ClassType
      def help(object, collapse=1, spacing=10):
      ""Print methods and doc string.
      Take module, class, list, dictionary, or string."""
      typeList = (BiultinFunctionType, BulitinMethodType, FunctionType, MethodType, ClassType)
      methodList = [method for method in dir(object) if type(getattr(object, emthod)) in typeList]
      processFunc = collapse and (lambda s: " ".join(split())) or (lambda s: s)
      print "\n".join(["%s %s" % (method.ljust(spacing),  processFunc(str(getattr(object, method).__doc__))) for method in methodList])
      if __name__ == "__main__":
      print help.__doc__
      # 输出
      >>> from apihelper import help
      >>> li = [ ]
      >>>help(li)
      append     L.append(object) -- append object to end
      count      L.count(value) -> integer -- return number of occurrences of value
      extend     L.extend(list) -- extend list by appending list elements
      index      L.index(value) -> integer -- return index of first occurrence of value
      insert     L.insert(index, object) -- insert object before index
      pop        L.pop([index]) -> item -- remove and return item at index (default last)
      remove     L.remove(value) -- remove first occurrence of value
      reverse    L.reverse() -- reverse *IN PLACE*
      sort       L.sort([cmpfunc]) -- sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1
    • 自我完成作业

      • 选用Import或者from module import导入模块
      • 可选和定名参数定义和调用函数
      • str强制转换为字符串表达式
      • 使用getattr动态函数得到函数和其他的什么引用
      • 扩展映射列表进行列表过滤
      • and-or的技巧的应用
      • 定义lambda函数
      • 将函数赋值给变量,然后通过引用变量调用函数。这种思考方式会提高对python的理解力???


  可通过本人转载的“Django实战系列”进行django的进一步学习;另外,实战系列的源代码下载地址:在实战系列文章中留言写下邮箱地址,一天内会发送给你全部源代码。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-59261-1-1.html 上篇帖子: 优雅的使用python之环境管理 下篇帖子: python dict字典
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表