python进阶笔记

Table of Contents

1 Collections

1.1 TODO defaultdict 这儿没懂

它可以在初始化时设置数据的类型,感觉有点像 C++ 中的 <list> 这些 容器一样。

    from collections import defaultdict

    colours = (
        ('Yasoob', 'Yellow'),
        ('Ali', 'Blue'),
        ('Arham', 'Green'),
        ('Ali', 'Black'),
        ('Yasoob', 'Red'),
        ('Ahmed', 'Silver'),
    )

    favourite_colours = defaultdict(list)

    for name, colour in colours:
        favourite_colours[name].append(colour)

    print(favourite_colours)

上面的例子用dict应该这样写:

    from collections import defaultdict

    colours = (
        ('Yasoob', 'Yellow'),
        ('Ali', 'Blue'),
        ('Arham', 'Green'),
        ('Ali', 'Black'),
        ('Yasoob', 'Red'),
        ('Ahmed', 'Silver'),
    )

    favourite_colours = dict()

    favourite_colours['xie'] = []
    favourite_colours['xie'].append('peng')

    for name, colour in colours:
        favourite_colours[name] = []
        favourite_colours[name].append(colour)

    print(favourite_colours)

另外,对一个键进行嵌套赋值时,dict会出异常:

    d = dict()
    d['xie']['peng'] = 'hi'

使用defaultdict可以解决。这个代码硬是没看懂。

    import collections
    tree = lambda: collections.defaultdict(tree)
    some_dict = tree()
    some_dict['colours']['favourite'] = "yellow"
    print some_dict

1.2 counter

我看reference,它是dict的一个子类。键对应的就是需要统计的元素,值就 是它的个数。迭代器中的元素可以使用counter来统计个数,counter还可以 用其它的 mapping 或者 counter 来初始化。

     from collections import Counter

     colours = (
         ('Yasoob', 'Yellow'),
         ('Ali', 'Blue'),
         ('Arham', 'Green'),
         ('Ali', 'Black'),
         ('Yasoob', 'Red'),
         ('Ahmed', 'Silver'),
     )

     favs = Counter(name for name, colour in colours)
     print(favs)

统计一个文件中的行:

     from collections import Counter
     with open('/tmp/kk.txt', 'rb') as f:
         line_count = Counter(f)
     print(line_count)

统计一个字符串:

     from collections import Counter

     c = Counter('xxxxxxie')
     print c

1.3 deque

双端队列

     from collections import deque

     d = deque()
     d.append(1)
     d.append(2)
     d.append(3)
     print d

     d = deque(range(5))
     print(len(d))
     print(d)

     print d.popleft()
     print d.pop()
     print d

它可以限制队列的大小,超出限制大小时,队列的另一端的数据会被挤出去, 另外,还可以使用extend来用列表扩展队列:

     from collections import deque

     d = deque(maxlen=10)
     for i in range(10):
         d.append(i)

     print d

     d.append(11)
     print d
     d.appendleft(12)
     print d

     d.extend([8, 8, 8])
     print d

1.4 namedtuple

命名元组和元组一样,都是不可变的。但是你可以不用索引来访问其中的元 素,可以像字典一样去访问它。

     from collections import namedtuple

     Animal = namedtuple('Animal', 'name age type')
     perry = Animal(name="perry", age=31, type="cat")

     print(perry)
     print perry.name
     print perry.age

     d = {'xie': 'peng'}
     print d['xie']
     print d.get('xie')

元组的属性值是不可变的,下面的代码会出问题:

     from collections import namedtuple

     test = namedtuple('test', 'name age')
     d = test(name='xiepeng', age=27)
     d.age = 1

命名元组很轻量,和元组占用差不多的内存。它比字典更快。

它也可以通过索引来访问元素,所以它其实是向后兼容元组的。

     from collections import namedtuple

     Animal = namedtuple('Animal', 'name age type')
     perry = Animal(name="perry", age=31, type="cat")
     print(perry[0])
     print(perry[1])

命名元组还可以转换为字典:

     from collections import namedtuple


     test = namedtuple('test', 'name age')

     a = test(name='xie', age=27)
     print type(a)
     print a
     d = a._asdict()
     print type(d)
     print d

1.5 enum.Enum

     # -*- coding: utf-8; -*-
     from collections import namedtuple
     from enum import Enum

     class Species(Enum):
         cat = 1
         dog = 2
         horse = 3
         aardvark = 4
         butterfly = 5
         owl = 6
         platypus = 7
         dragon = 8
         unicorn = 9
         # 依次类推

         # 但我们并不想关心同一物种的年龄,所以我们可以使用一个别名
         kitten = 1  # (译者注:幼小的猫咪)
         puppy = 2   # (译者注:幼小的狗狗)

     Animal = namedtuple('Animal', 'name age type')
     perry = Animal(name="Perry", age=31, type=Species.cat)
     drogon = Animal(name="Drogon", age=4, type=Species.dragon)
     tom = Animal(name="Tom", age=75, type=Species.cat)
     charlie = Animal(name="Charlie", age=2, type=Species.kitten)

     print charlie.type == tom.type
     print charlie.type

     print Species(1)
     print Species['cat']
     print Species.cat

2 lambda

和elisp一样,它就是匿名函数。其函数原型如下:

    lambda 参数:操作(参数)

例子:

    add = lambda x, y: x + y

    print add(2, 3)

排序时的key函数:

    a = [(1, 2), (4, 1), (9, 10), (13, -3)]
    a.sort(key=lambda x: x[1])
    print a

    a.sort(key=lambda x: x[0])
    print a

    print sorted(a, key=lambda x: x[1])


    list1 = [9, 7, 5]
    list2 = [10, 8, 6]

    data = zip(list1, list2)
    print data
    data.sort()
    print data
    print '================'
    print zip(*data)
    list1, list2 = map(lambda t: list(t), zip(*data))
    print '################'
    print list1
    print list2

3 推导式

集合推导式

    squared = {x**2 for x in [1, 1, 2]}
    print(squared)

列表推导式:

    multiples = [i for i in range(30) if i % 3 is 0]
    print(multiples)

    squared = []
    for x in range(10):
        squared.append(x**2)
    print squared

    squared2 = [x**2 for x in range(10)]
    print squared2

字典推导式:

    mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}

    mcase_frequency = {
        k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0)
        for k in mcase.keys()
    }
    print mcase_frequency

可以使用来对换一个字典的键值:

    d = {
        'xie': 'peng',
        'hi': 'hao'
    }

    print d
    print {v: k for k, v in d.items()}

4 上下文管理

使用with进行上下文管理,非常方便:

    with open('xxx', 'rb') as f:
        f.read()
        ...

可以自己定义上下文管理器:

    class File(object):
        def __init__(self, filename, method):
            self.file_obj = open(filename, method)

        def __enter__(self):
            return self.file_obj

        def __exit__(self, type, value, traceback):
            self.file_obj.close()


    with File('/tmp/kk.txt', 'r') as f:
        print f.read()

它真的起作用了!

大概的过程:

  1. with 先暂存下 __exit__ 方法。
  2. 调用 __enter__ 方法,把它的返回值赋给 f
  3. 通过f执行对应的操作。
  4. 最后 with 语句调用 __exit__ 做后续处理,这里就是直接关闭文件 句柄。

下面我们来看下 __exit__ 的其它几个参数,如果在 with 执行的时候发 生了异常,它会将异常的 type, value, traceback 都传递给 __exit__ 。让它来处理异常。两种情况:

  1. 如果 __exit__ 返回的是True,那么这个异常就被优雅地处理了。
  2. 如果 exit__ 返回的是True以外的任何东西,那么这个异常将被 with 语句抛出。

下面这个例子我们就自己handle了错误:

    class File(object):
        def __init__(self, file_name, method):
            self.file_obj = open(file_name, method)
        def __enter__(self):
            return self.file_obj
        def __exit__(self, type, value, traceback):

            print("Exception has been handled")
            print type
            print value
            print traceback

            self.file_obj.close()
            return True

    with File('demo.txt', 'w') as opened_file:
        opened_file.undefined_function()

还可以使用生成器和装钸器来实现上下文管理。Python有个contextlib模块专 门用于这个目的。我们可以使用一个生成器函数来实现一个上下文管理器,而 不是使用一个类。

    from contextlib import contextmanager

    @contextmanager
    def open_file(name):
        f = open(name, 'w')
        yield f
        f.close()

5 装钸器

在python中,函数是对象。可以进行赋值等操作:

    # -*- coding: utf-8; -*-
    def hi(name="yasoob"):
        return "hi " + name

    print(hi())
    # output: 'hi yasoob'

    # 我们甚至可以将一个函数赋值给一个变量,比如
    greet = hi
    # 我们这里没有在使用小括号,因为我们并不是在调用hi函数
    # 而是在将它放在greet变量里头。我们尝试运行下这个

    print(greet())
    # output: 'hi yasoob'

    # 如果我们删掉旧的hi函数,看看会发生什么!
    del hi
    print(hi())
    #outputs: NameError

    print(greet())
    #outputs: 'hi yasoob'

函数中可以定义函数:

    def out_fun():

        def inter_fun1():
            print 'in inter_fun1'

        def inter_fun2():
            print 'in inter_fun2'
        
        print 'begin out_fun'

        inter_fun1()
        inter_fun2()
    
        print 'end_out_fun'
    
    out_fun()

内部的 inter_fun1inter_fun2 在外部是不可见的。

函数也可以返回函数:

    def re_fun():
        print 'in re_fun'

        def hi():
            print 'hi this is the returned function'
            return 'this is return value'

        return hi


    a = re_fun()

    print a()

函数也可以做为参数传递给另一个函数:

    def a(fun):
        print 'a will call function %s' % fun.__name__
        fun()

    def hi():
        print 'hi'

    def hello():
        print 'hello,world'
    
    a(hi)
    a(hello)

装钸器就是让你能在你的函数的前后去执行代码:

    def a_new_decorator(a_func):

        def wrapTheFunction():
            print("I am doing some boring work before executing a_func()")

            a_func()

            print("I am doing some boring work after executing a_func()")

        return wrapTheFunction

    def a_function_requiring_decoration():
        print("I am the function which needs some decoration to remove my foul smell")

    a_function_requiring_decoration()
    #outputs: "I am the function which needs some decoration to remove my foul smell"

    a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
    #now a_function_requiring_decoration is wrapped by wrapTheFunction()

    a_function_requiring_decoration()
    #outputs:I am doing some boring work before executing a_func()
    #        I am the function which needs some decoration to remove my foul smell
    #        I am doing some boring work after executing a_func()

如果我们按照python中的语法来写的话,这个装钸器应该是这样的:

    def a_new_decorator(a_func):

        def wrapTheFunction():
            print("I am doing some boring work before executing a_func()")

            a_func()

            print("I am doing some boring work after executing a_func()")

        return wrapTheFunction

    @a_new_decorator
    def a_function_requiring_decoration():
        """Hey you! Decorate me!"""
        print("I am the function which needs some decoration to "
              "remove my foul smell")

    a_function_requiring_decoration()
    #outputs: I am doing some boring work before executing a_func()
    #         I am the function which needs some decoration to remove my foul smell
    #         I am doing some boring work after executing a_func()

    #the @a_new_decorator is just a short way of saying:
    a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)

但是这样会有一个问题:

    def a_new_decorator(a_func):

        def wrapTheFunction():
            print("I am doing some boring work before executing a_func()")

            a_func()

            print("I am doing some boring work after executing a_func()")

        return wrapTheFunction

    @a_new_decorator
    def a_function_requiring_decoration():
        """Hey you! Decorate me!"""
        print("I am the function which needs some decoration to "
              "remove my foul smell")

    a_function_requiring_decoration()
    a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)

    print a_function_requiring_decoration.__name__

最后函数的 __name__ 属性被覆盖了。这并不是我们想要的。python中有一 个 functools.wraps 可以用来解决这个问题,他可以保留被装钸的函数的 __name____doc__ 属性。

    from functools import wraps

    def a_new_decorator(a_func):
        @wraps(a_func)
        def wrapTheFunction():
            print("I am doing some boring work before executing a_func()")
            a_func()
            print("I am doing some boring work after executing a_func()")
        return wrapTheFunction

    @a_new_decorator
    def a_function_requiring_decoration():
        """Hey yo! Decorate me!"""
        print("I am the function which needs some decoration to "
              "remove my foul smell")

    print(a_function_requiring_decoration.__name__)
    # Output: a_function_requiring_decoration

web应用认证的时候常用装钸器来这样写:

    from functools import wraps

    def requires_auth(f):
        @wraps(f)
        def decorated(*args, **kwargs):
            auth = request.authorization
            if not auth or not check_auth(auth.username, auth.password):
                authenticate()
            return f(*args, **kwargs)
        return decorated

记录日志也是常使用的:

    from functools import wraps

    def logit(func):
        @wraps(func)
        def with_logging(*args, **kwargs):
            print(func.__name__ + " was called")
            return func(*args, **kwargs)
        return with_logging

    @logit
    def addition_func(x):
       """Do some math."""
       return x + x


    result = addition_func(4)
    # Output: addition_func was called

如果需要定义带参数的装钸器:

    from functools import wraps

    def logit(logfile='out.log'):
        def logging_decorator(func):
            @wraps(func)
            def wrapped_function(*args, **kwargs):
                log_string = func.__name__ + " was called"
                print(log_string)
                # 打开logfile,并写入内容
                with open(logfile, 'a') as opened_file:
                    # 现在将日志打到指定的logfile
                    opened_file.write(log_string + '\n')
                return func(*args, **kwargs)
            return wrapped_function
        return logging_decorator

    @logit()
    def myfunc1():
        pass

    myfunc1()
    # Output: myfunc1 was called
    # 现在一个叫做 out.log 的文件出现了,里面的内容就是上面的字符串

    @logit(logfile='func2.log')
    def myfunc2():
        pass

    myfunc2()
    # Output: myfunc2 was called
    # 现在一个叫做 func2.log 的文件出现了,里面的内容就是上面的字符串

可以类似于这样来理解:

    logit(logfile='out.log')(myfunc1)
    logit(logfile='func2.log')(myfunc2)

函数式编程,函数是第一类数据,可以做为参数传递,也可以做为返回值。所 以这种带参数的装钸器执行就是类似于上面这样。

装钸器还可以实现为一个类,这就更灵活啦。比如上面的记录日志的同时,还 想再发邮件给管理员。

    from functools import wraps


    class clogit(object):
        """Documentation for clogit

        """
        def __init__(self, logfile):
            super(clogit, self).__init__()
            self.logfile = logfile

        def __call__(self, func):
            @wraps(func)
            def wrapper(*args, **kargs):
                logstring = 'function %s is called' % func.__name__
                func(*args, **kargs)

                with open(self.logfile, 'wb') as f:
                    f.write(logstring)

                self.notify(logstring)

            return wrapper

        def notify(self, s):
            # clogit not notify
            pass

    @clogit('/tmp/logit')
    def function_test():
        print 'this is function'

    function_test()

这个感觉有点像:

    clogit('/tmp/logit').__call__(function_test)

它比 嵌套函数的方式 更整洁一些。而且扩展也很方便啦,现在我们可以定义 一个可以发邮件的子类:

    from functools import wraps


    class clogit(object):
        """Documentation for clogit

        """
        def __init__(self, logfile='/tmp/logit'):
            super(clogit, self).__init__()
            self.logfile = logfile

        def __call__(self, func):
            @wraps(func)
            def wrapper(*args, **kargs):
                logstring = 'function %s is called' % func.__name__
                func(*args, **kargs)

                with open(self.logfile, 'wb') as f:
                    f.write(logstring)

                self.notify(logstring)

            return wrapper

        def notify(self, s):
            # clogit not notify
            pass


    class email_andlogit(clogit):
        """Documentation for email_andlogit

        """
        def __init__(self, emailaddress='xxx@gmail.com', *args, **kargs):
            super(email_andlogit, self).__init__(*args, **kargs)
            self.emailaddress = emailaddress

        def notify(self, s):
            print 'I will email %s to %s' % (s, self.emailaddress)
            # send email here

    @email_andlogit('peng@gmail.com', '/tmp/emaillogit')
    def test_email():
        print 'this is function'
    test_email()

这样, email_andlogit 不仅会写入日志,还会发送一封邮件给管理员啦。

6 函数式编程

6.1 Map

把一个函数映射到一个列表中的每个元素。一般和匿名函数(lambda)结合 使用。先看看下面这段代码:

     items = [1, 2, 3, 4, 5]
     squared = []
     for i in items:
         squared.append(i**2)
     print squared

修改为map后可以这样:

     items = [1, 2, 3, 4, 5]
     squared = list(map(lambda x: x**2, items))
     print squared

map不仅可以应用到全是数据的列表,还可以应用到全是函数的列表上(因为 函数式编程可以把函数也理解为数据,所以其实这两种也没差):

     # -*- coding: utf-8; -*-
     def add(x):
         return x + x

     def multi(x):
         return x * x

     f = [add, multi]

     # 这里的x分别就是上面的函数,一个一个进行调用罗
     value = map(lambda x: x(3), f)

     # 这里加了list转换,为了兼容,python2中map返回列表,3中map返回迭代器。
     print list(value)

map写一个把所有list中字符串转换为首字母大写其它小写的形式:

     def f(x):
         a = x.lower()
         return ''.join(a[0].upper()) + a[1:]

     b = ['XIE', 'sd', 'PDFJAF', 'aaaaaaaasdfasDSFFDSAF']
     print map(f, b)

6.2 Filter

和map类似的用法,它可以过滤满足条件的元素出来。

     num = [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]
     value = filter(lambda x: x < 0, num)
     print(list(value))

filter是内置函数,它类似于for,但是更快。但是大部分情况下,还是 推导式 更优雅一些。

6.3 Reduce

reduce把一个函数作用在一个序列[x1, x2, x3…]上,这个函数必须接收两 个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:

     reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

这样的话写一个求和的函数可以这样:

     a = range(201)
     print reduce((lambda x, y: x + y), a)

reduce求积:

     def fun(l):
         return reduce((lambda x, y:x * y), l)

     print fun(range(1, 5))

[1, 3, 5, 7, 9] 转换为13579可以这样:

     a = [1, 3, 5, 7, 9]
     def f(x, y):
         return x * 10 + y

     print reduce(f, a)

因为字符串也是一个序列,那么加上map我们可以这样搞一个字符串转换数字 的函数:

     def fn(x, y):
         return x * 10 + y

     def char2num(s):
         return {'0': 0,
                 '1': 1,
                 '2': 2,
                 '3': 3,
                 '4': 4,
                 '5': 5,
                 '6': 6,
                 '7': 7,
                 '8': 8,
                 '9': 9,
         }[s]

     a = map(char2num, '13579')
     b = reduce(fn, map(char2num, '13579'))
     print a
     print b
     print type(b)

整合起来弄成一个函数就可以是这样:

     def mystr2int(s):
         def fn(x, y):
             return x * 10 + y

         def char2num(s):
             return {'0': 0,
                     '1': 1,
                     '2': 2,
                     '3': 3,
                     '4': 4,
                     '5': 5,
                     '6': 6,
                     '7': 7,
                     '8': 8,
                     '9': 9,
             }[s]

         return reduce(fn, map(char2num, s))

     result = mystr2int('13579')
     print type(result), result

7 set 数据结构

它与列表类似,但是不能包括重复的值,它可以根据一个list来初始化:

    l = [1, 2, 3, 4, 1]
    s = set(l)
    print l
    print s

求交集:

    a = set([1, 2, 3, 4, 5])
    b = set([3, 5])
    print a.intersection(b)
    print a & b

差集:

    a = set([1, 2, 3, 4, 5])
    b = set([3, 5])

    print a - b

并集:

    a = set([1, 2, 3, 4, 5])
    b = set([3, 5, 7])

    print a | b

还可以使用符号来创建集合:

    a_set = {'red', 'blue'}
    print type(a_set)

8 三元运算符

看看下面的例子:

    a = True
    b = 'yes' if a else 'no'
    print b

    a = False
    b = 'yes' if a else 'no'
    print b

9 Global

    def fun():
        global s
        print 'this is in fun'
        s = range(10)

    fun()
    print s

在函数内部使用 global 来声明变量,可以使该变量在全局范围都能访问。 但是一般应该避免这样使用。

10 可变对象和不可变对象

可变就是可以被改动,不可变就是常量的意思。

    foo = ['hi']
    bar = foo
    foo += ['xie']
    print bar

其实这两个变量指向的只是同一个东西啦。再来看下下面的例子:

    def add_to(num, target=[]):
        target.append(num)
        return target

    print add_to(1)
    # Output: [1]

    print add_to(2)
    # Output: [2]

    print add_to(3)
    # Output: [3]

为什么这里还是一个累加的结果呢?因为在python中当函数被定义时,默认参 数只会被调用一次,而不是每次调用都会重新运算。 应该永远不要定义一个 可变类型的默认参数,除非你知道你在做什么。 上面的例子要实现不累加的 效果,需要这样做:

    def addto(num, target=None):
        if target == None:
            target = []

        target.append(num)
        return target

    print addto(1)
    print addto(2)
    print addto(3)

10.1 总结可变类型和不可变类型

不可变类型:

  1. 元组 (1, 2)
  2. string :可以发现s和d都是指向的同一块内存。但是使用切片后,c其实 是copy出来。

            s = 'xiepeng'
            d = 'xiepeng'
            print id(s)
            print id(d)
    
            c = d[1:]
            print id(s)
            print id(d)
            print id(c)
    
  3. int和float。77在内存中是同一块地址,但是 j+1 ,其实也是执行了 copy的动作。

            def int_test(): 
                i = 77
                j = 77
                print(id(77))                    #140396579590760
                print('i id:' + str(id(i)))      #i id:140396579590760
                print('j id:' + str(id(j)))      #j id:140396579590760
                print i is j                     #True
                j = j + 1
                print('new i id:' + str(id(i)))  #new i id:140396579590760
                print('new j id:' + str(id(j)))  #new j id:140396579590736
                print i is j                     #False
    
            if __name__ == '__main__':
                int_test()
    

可变类型:

  1. dict和list。因为是可变的,所以这里没有拷贝。都是在一块内存里搞事 情。

            def dict_test():
                a = {}
                b = a
                print(id(a))
                a['a'] = 'hhhh'
                print('id a:' + str(id(a)))
                print('a:' + str(a))
                print('id b:' + str(id(b)))
                print('b:' + str(b))
    
            if __name__ == '__main__':
                dict_test()
    

python函数调用的时候都是传递的引用,也就是传给函数原变量实际指向的 内存空间。如果传递的是可变参数类型,在函数内部对该参数的修改会体现 到原变量上。这样会出问题的。应避免。

     def fun(x):
         print 'inter x = %s before modify' % x
         x.append(5)
         print 'inter x = %s after modify' % x
    

     a = [1,2,3]
     print 'outer before function a = %s' % a
     fun(a)
     print 'outer after function a = %s' % a

换成不可变类型的string表现就正常了。

     def fun(x):
         print 'inter x = [{s}] before modify'.format(s=x)
         x = x + 'end'
         print 'inter x = [{s}] after modify'.format(s=x)


     a = 'xie'
     print 'outer before function a = [{s}]'.format(s=a)
     fun(a)
     print 'outer after function a = [{s}]'.format(s=a)

11 python实用命令

11.1 共享文件目录

直接进到目录这样:

    # Python 2
    python -m SimpleHTTPServer

    # Python 3
    python -m http.server

11.2 脚本性能分析

     python -m cProfile main.py

备注:cProfile是一个比profile更快的实现,因为它是用c写的

11.3 CSV转换为json

     python -c "import csv,json;print json.dumps(list(csv.reader(open('csv_file.csv'))))"

11.4 列表辗平

     import itertools

     a_list = [[1, 2], [3, 4], [5, 6]]
     print list(itertools.chain.from_iterable(a_list))

11.5 一行式的构造器

避免类初始化时大量重复的赋值语句:

     # -*- coding: utf-8; -*-
     class A(object):
         def __init__(self, a, b, c, d, e, f):
             self.__dict__.update({k: v for k, v in locals().items() if k != 'self'})


     # 上面语句可以工作请看下面:
     class C(object):
         """Documentation for C

         """
         def __init__(self, a, b, c=4):
             print locals()
             print self.__dict__
             self.__dict__.update({'z': 15})
             print self.__dict__
             print self.z

     c = C(2, 3)

11.6 命令行下编译py文件

     python -m py_compile file.py file2.py

12 对象自省

自省(introspection),在计算机编程领域里,是指在运行时来判断一个对象 的类型的能力。它是Python的强项之一。Python中所有一切都是一个对象,而 且我们可以仔细勘察那些对象。

12.1 dir

它返回一个列表,列出了一个对象的所有属性和方法。

     a = 2
     print dir(a)

如果不传入参数,它可以返回当前作用域的所有名字:

     a = 2
     b = a
     print dir()

12.2 type和id

     print(type(1))
     print(type('xiepeng'))

     print(id(7))
     print(id(7))

12.3 inspect

     import inspect
     print(inspect.getmembers(str))
     print(dir(str))

它和 dir 的区别是dir只返回 name ,而它返回 (name, attribute) 这样的元组。

Author: Peng Xie

Created: 2018-10-01 Mon 21:36