zoukankan      html  css  js  c++  java
  • python 基础部分重点复习整理--从意识那天开始进阶--已结

    pythonic 风格编码

    入门python好博客
    进阶大纲
    有趣的灵魂
    老齐的教程
    老齐还整理了很多精华
    听说 fluent python + pro python 这两本书还不错!

    元组三种遍历,有点像字有四种写法一样。。。苦笑

    for index in range(0,len(tuple_1)):
    ...     print(tuple_1[index])
    
    >>> for index in range(0,len(tuple_1)):
    ...     print('{}--{}'.format(index,tuple_1[index]))
    
    
    >>> tuple_1 = (1,2,'hello','world')
    >>> for content in tuple_1:
    ...     print(content)
    
    >>> for index,enum in enumerate(tuple_1):
    ...     print('{}--{}'.format(index,enum))
    
    # 黑魔法咩?  map ,reduce
    from functools import reduce
    def str2int(s):
        Digital = {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}
        return Digital[s]
    
    def str_reduce(s):
        l = list(map(str2int,s))
        if not isinstance(s, str):
            raise ValueError('输入不是字符串类型!')
        return reduce(lambda x,y:x+y,[v * 10**(len(l)-i-1) for  i , v in enumerate(l)])
    
    str_reduce('213')
    
    # 更加 逆天的 map 用法,不论传入的 list 是普通值 还是 func 都行
    
    >>> for i in range(10):
    ...     print(list(map(lambda x:x(i),[lambda x:x+x,lambda x:x**2])))
    
    
    # filter 用法
    >>> list_1 = [i for i in range(30) if i%2 == 1]
    >>> list_1
    [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29]
    >>> list(filter(lambda x:x<10,list_1))
    [1, 3, 5, 7, 9]
    
    
    
    tuple 互转   tuple(list_1)    ,  list(tuple_2)
    >>> import os
    >>> print(os.path.abspath('.'))
    C:UsersFrankLiDesktop
    >>> import sys
    >>> print(sys.argv)
    ['']
    >>> print(sys.executable)
    D:Program Files (x86)pythonpython.exe
    
    • 列表生成式 vs 生成器表达式
    >>> [x for x in list_1 if x%2==1]
    [1, 3, 5]
    
    >>> (x for x in list_1 if x%2==1)
    <generator object <genexpr> at 0x033C2660>
    
    >>> gen = (x for x in range(0,10) if x%3==1)
    >>> for x in gen:
    ...     print(x)
    ...
    1
    4
    7
    
    
    >>> #这是一个生成器应用,斐波拉契数列
    ... def fib(max):
    ...     n,a,b=0,1,1
    ...     while n<=max:
    ...         yield b
    ...         a,b=b,a+b
    ...         n=n+1
    ...     return 'Nore More!'
    ...
    >>> for f in fib(6):
    ...     print('fib: {}'.format(f))
    ...
    fib: 1
    fib: 2
    fib: 3
    fib: 5
    fib: 8
    fib: 13
    fib: 21
    
    >>> def fib(x):
    ...     a,b = 1,1
    ...     for i in range(x):
    ...         yield a
    ...         a,b = b,a+b
    ...
    >>> for i in fib(10):
    ...     print(i)
    ...
    1
    1
    2
    3
    5
    8
    13
    21
    34
    55
    
    #获取生成器重的 return 返回值 Nore More!
    
    >>> g = fib(6)
    >>> while True:
    ...    try:
    ...        x=next(g)
    ...        print('g: {}'.format(x))
    ...    except StopIteration as e:
    ...        print('evalue: {}'.format(e.value))
    ...        break
    ...
    g: 1
    g: 2
    g: 3
    g: 5
    g: 8
    g: 13
    g: 21
    evalue: Nore More!
    
    # string 也是序列可以被迭代 iter(s) 即可
    >>> s = 'google'
    >>> s_iter = iter(s)
    >>> while True:
    ...     try:
    ...         print(next(s_iter))
    ...     except StopIteration as stopIter:
    ...         print('done')
    ...         break
    ...
    g
    o
    o
    g
    l
    e
    done
    
    
    >>> # 杨辉三角末尾补零两数相加大法
    ... def triangle():
    ...     l=[1]
    ...     while True:
    ...         yield l
    ...         l.append(0)
    ...         l=[l[i-1]+l[i] for i in range(0,len(l))]
    
    
    调用杨辉三角生成器
    >>> n=0
    >>> for e in triangle():
    ...     n=n+1
    ...     print(e,'	')
    ...     if n==10:
    ...         break
    ...
    [1]
    [1, 1]
    [1, 2, 1]
    [1, 3, 3, 1]
    [1, 4, 6, 4, 1]
    [1, 5, 10, 10, 5, 1]
    [1, 6, 15, 20, 15, 6, 1]
    [1, 7, 21, 35, 35, 21, 7, 1]
    [1, 8, 28, 56, 70, 56, 28, 8, 1]
    [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
    
    

    迭代器

    Generator 天然的 迭代器 
    而  tuple , list 等 序列如果要编程 迭代器 需要 iter(list_1) 、iter(tuple_2)
    >>> from collections import Iterator
    >>> isinstance((1,2,3,4),Iterator)
    False
    >>> isinstance((x for x in range(10) if x%2==0),Iterator)
    True
    >>>
    >>> isinstance(iter((1,2,3,4)),Iterator)
    True
    >>>
    
    >>> list_1 = [1,2,3,4]
    >>> list_1_iter = iter(list_1)
    >>> while True:
    ...     try:
    ...         x=next(list_1_iter)
    ...         print('x:{}'.format(x))
    ...     except StopIteration as e:
    ...         print('e.value: {}'.format(e.value))
    ...         break
    ...
    x:1
    x:2
    x:3
    x:4
    e.value: None
    
    
    • python map reduce 实现
    >>> def pow2(val):
    ...     return val**2
    ...
    >>> list_1 = [1,2,3,4,5]
    >>> list(map(pow2,list_1))
    [1, 4, 9, 16, 25]
    >>> def sum(x,y):
    ...     return x+y
    ...
    >>> from functools import reduce
    >>> reduce(sum,list(map(pow2,list_1)))
    55
    
    强悍的 lambda
    
    >>> from functools import reduce
    >>> reduce(lambda x,y:x+y,list(map(lambda x:x**2,[1,2,3,4,5,6,7])))
    
    • 注意区别 Iterable 可迭代 与 Iterator 惰性迭代器

    高阶函数

    >>> def lazy_sum(*args):
    ...     def sum():
    ...         ax=0
    ...         for n in args:
    ...          ax=ax+n
    ...         return ax
    ...     return sum
    ...
    >>> lazy_sum(1,2,3,4,5)
    <function lazy_sum.<locals>.sum at 0x013902B8>
    >>> f=lazy_sum(1,2,3,4,5)
    >>> f()
    15
    

    win 下 python 清屏

    >>> import os
    >>> def clear():
    ...     os.system('cls')
    
    
    >>> import os
    >>> def cls():
    ...     if os.name.upper() == 'NT':
    ...         os.system('cls')
    ...     else:
    ...         os.system('clear')
    
    

    可变参数,巧调用

    python的可变参数和关键字参数(*args **kw)

    讲*args 可变参数, **kw 关键字参数非常好的文章

    >>> def test(*args):
    ...     sum=0
    ...     for n in args:
    ...         sum=sum+n
    ...     return sum
    ... test([1,2,3,4])
      File "<stdin>", line 6
        test([1,2,3,4])
           ^
    SyntaxError: invalid syntax
    >>> test(*[1,2,3,4])
    10
    >>> test(1,2,3,4)
    10
    
    
    在 python3 中已经废除了 dict 的 has_key 方法 用  key in dict 这种方式代替
    
    >>> def person(*args,**kw):
    ...     l=[]
    ...     for n in args:
    ...         l.append(n)
    ...     dic=kw
    ...     if 'city' in dic:
    ...         pass
    ...     if 'job' in dic:
    ...         pass
    ...     print('l:{} dic {}'.format(l,dic))
    ...
    >>> person('tom',2,city='changsha',job='unknown')
    l:['tom', 2] dic {'city': 'changsha', 'job': 'unknown'}
    
    进阶
    >>> extra = {'city':'cs','job':'developer'}
    >>> tuple=('tom',30)
    >>> person(*tuple,**extra)
    l:['tom', 30] dic {'city': 'cs', 'job': 'developer'}
    >>>
    

    装饰器类似于 java 里的 AOP 动态代理,或者继承组合

    >>> import functools
    >>> #自定义文本消息的事务装饰器
    ... def trans(text):
    ...     def decorater(func):
    ...         @functools.wraps(func)
    ...         def wrapper(*args,**kw):
    ...             print('{} {}'.format(text,func.__name__))
    ...             return func(*args,**kw)
    ...         return wrapper
    ...     return decorater
    ...
    >>> @trans('开启事务'):
      File "<stdin>", line 1
        @trans('开启事务'):
                      ^
    SyntaxError: invalid syntax
    >>> @trans('开启事务')
    ... def trans_func():
    ...     print('我是一个要被事务装饰的函数')
    ...
    >>> trans_func()
    开启事务 trans_func
    我是一个要被事务装饰的函数
    
    >>> from functools import wraps
    >>> def my_decorator(func):
    ...     @wraps(func)
    ...     def wrap_func():
    ...         print('before...')
    ...         func()
    ...         print('after...')
    ...     return wrap_func
    ...
    >>> @my_decorator
    ... def func_a():
    ...     print('func_a...')
    ...
    >>> func_a()
    before...
    func_a...
    after...
    >>> func_a.__name__
    'func_a'
    
    
    >>> from functools import wraps
    >>> def custom_text(text):
    ...     def decorater(func):
    ...         @wraps(func)
    ...         def wrap_decorated(*args,**kwargs):
    ...             print('{} {}'.format(text,func.__name__))
    ...             return func(*args,**kwargs)
    ...         return wrap_decorated
    ...     return decorater
    ...
    >>> @custom_text('自定义文本信息...')
    ... def tran(*args,**kwargs):
    ...     for i in args:
    ...         print(i,end=',')
    ...     for key,value in kwargs.items():
    ...         print('{}-->{}'.format(key,value))
    ...     print('事务...社会...')
    ...
    >>> args = (1,'abc',3)
    >>> from functools import wraps
    >>> kwargs = dict(name='Frank',age=18)
    >>> tran(*args,**kwargs)
    自定义文本信息... tran
    1,abc,3,name-->Frank
    age-->18
    事务...社会...
    
    
    from functools import wraps
    
    class LogIt(object):
        def __init__(self,log_file='out.log'):
            self._log_file = log_file
            
        @property
        def log_file(self):
            return self._log_file
        @log_file.setter
        def log_file(self,log_file):
            self._log_file = log_file
        def __call__(self,func):
            @wraps(func)
            def wrap_func(*args,**kwargs):
                log_string = '{} {}'.format(func.__name__,'called...')
                print('wrap_func logging...{}'+log_string)
                with open(self.log_file,'a') as logfile:
                    logfile.write(log_string+'
    ')
                self.notify(log_string)
                return func(*args,**kwargs)
            return wrap_func
        def notify(self,log_string):
            print('notify logging...{}'.format(log_string))
    
    @LogIt('out1.log')
    def trans(*args,**kwargs):
        for i in args:
            print(i,end=',')
        for key,value in kwargs.items():
            pritn('{}<-->{}'.format(key,value))
            
    args = ('trans start..',1,2,'test')
    kwargs = dict(name='Frank',age=18)
    trans(*args,*kwargs)
    
    wrap_func logging...{}trans called...
    notify logging...trans called...
    trans start..,1,2,test,name,age,
    
    

    偏函数,可以见 functools 多么强大值得好好学学

    >>> convert_int_from_8 = functools.partial(int,base=8)
    >>> convert_int_from_8(12345)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: int() can't convert non-string with explicit base
    >>> convert_int_from_8('12345')
    5349
    
    # kw 这种 dict 传值也是可以的
    >>> kw = {'base':8}
    >>> convert_int_from_8 = functools.partial(int,base)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'base' is not defined
    >>> convert_int_from_8 = functools.partial(int,**kw)
    >>> convert_int_from_8('123456')
    
    最后,创建偏函数时,实际上可以接收函数对象、*args和**kw这3个参数,当传入:
    
    int2 = functools.partial(int, base=2)
    实际上固定了int()函数的关键字参数base,也就是:
    
    int2('10010')
    相当于:
    
    kw = { 'base': 2 }
    int('10010', **kw)
    当传入:
    
    max2 = functools.partial(max, 10)
    实际上会把10作为*args的一部分自动加到左边,也就是:
    
    max2(5, 6, 7)
    相当于:
    
    args = (10, 5, 6, 7)
    max(*args)
    结果为10。
    
    # 总结 就是 偏函数 其实就是把原本参数很多的函数简化参数,便于使用
    #当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单
    

    模块

    # -*- coding: utf-8 -*-
    'test module'
    __author__ = 'Frank Li'
    import sys
    def test():
        args=sys.argv
        if len(args)==1:
            print('hello world!')
        elif len(args)==2:
            print('hello {}'.format(args[1]))
        else:
            print('to many args!')
    
    if __name__ == '__main__':
        test()
    

    模块搜索路径

    默认情况下,Python解释器会搜索当前目录、所有已安装的内置模块和第三方模块,搜索路径存放在sys模块的path变量中:
    
    >>> import sys
    >>> sys.path
    ['', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python36.zip', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6', ..., '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages']
    如果我们要添加自己的搜索目录,有两种方法:
    
    一是直接修改sys.path,添加要搜索的目录:
    
    >>> import sys
    >>> sys.path.append('/Users/michael/my_py_scripts')
    这种方法是在运行时修改,运行结束后失效。
    
    第二种方法是设置环境变量PYTHONPATH,该环境变量的内容会被自动添加到模块搜索路径中。设置方式与设置Path环境变量类似。注意只需要添加你自己的搜索路径,Python自己本身的搜索路径不受影响。
    

    面向对象

    >>> class Test(object):
    ...     def __init__(self,*args):
    ...         self.name,self.age=args[0],args[1]
    ...
    >>> t = Test('frank',18)
    >>> t
    <__main__.Test object at 0x02F00AB0>
    >>> t.name
    'frank'
    >>> t.age
    18
    

    再进一阶

    >>> class Person(object):
    ...     def __init__(self,name,age,*args,**kw):
    ...         self.name,self.age = name,age
    ...         for arg in args:
    ...             print('arg: {}'.format(arg))
    ...         for key in kw:
    ...             print('key: {}--> value: {}'.format(key,kw[key]))
    ...
    >>> args=('a',1,2,'b')
    >>> kw ={'city':'changsha','job':'developer'}
    >>> Person('frank',18,*args,**kw)
    arg: a
    arg: 1
    arg: 2
    arg: b
    key: city--> value: changsha
    key: job--> value: developer
    <__main__.Person object at 0x02F00DD0>
    
    
    
    >>> class Student(object):
    ...     def __init__(self,name,score,*args,**kw):
    ...         self.name,self.score = name,score
    ...         for arg in args:
    ...             print('arg: {}'.format(arg))
    ...         for key in kw:
    ...             if key=='city':
    ...                 self.city =kw[key]
    ...             elif key=='job':
    ...                 self.job=kw[key]
    ...             else:
    ...                 pring('key: {} --> value: {}'.format(key,kw[key]))
    ...     def get_grade(self):
    ...             if  self.score >= 90:
    ...                 return '优'
    ...             if 70<self.score<90:
    ...                 return '良'
    ...             elif 60<self.score<=70:
    ...                 return '几个'
    ...             else:
    ...                 return '不及格'
    
    >>> student = Student('frank',80,*args,**kw)
    arg: a
    arg: 1
    arg: 2
    arg: 3
    arg: c
    arg: d
    >>> student.city
    'changsha'
    >>> student.get_grade()
    '良'
    >>>
    
    区别于 java 这种静态语言 , python 是动态语言
    小结
    类是创建实例的模板,而实例则是一个一个具体的对象,各个实例拥有的数据都互相独立,互不影响;
    
    方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据;
    
    通过在实例上调用方法,我们就直接操作了对象内部的数据,但无需知道方法内部的实现细节。
    
    和静态语言不同,Python允许对实例变量绑定任何数据,也就是说,对于两个实例变量,虽然它们都是同一个类的不同实例,但拥有的变量名称都可能不同:
    
    >>> bart = Student('Bart Simpson', 59)
    >>> lisa = Student('Lisa Simpson', 87)
    >>> bart.age = 8
    >>> bart.age
    8
    >>> lisa.age
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Student' object has no attribute 'age'
    

    访问权限控制

    此方法不推荐, 应该用 set_gender() 而不是 bart._Student__gender 这种方式修改 gender 属性
    >>> class Student(object):
    ...     def __init__(self,name,gender):
    ...         self.name=name
    ...         self.__gender=gender
    ...     def get_gender(self):
    ...         return self.__gender
    ...
    >>> bart = Student('Bart', 'male')
    >>> if bart.get_gender() != 'male':
    ...     print('测试失败!')
    ... else:
    ...     bart._Student__gender='female'
    ...     if bart.get_gender() != 'female':
    ...         print('测试失败!')
    ...     else:
    ...         print('测试成功!')
    ...
    测试成功!
    
    
    正确做法:
    
    >>> class Student(object):
    ...     def __init__(self,name,gender):
    ...         self.name,self.__gender=name,gender
    ...     def set_gender(self,gender):
    ...         self.__gender = gender
    ...     def get_gender(self):
    ...         return self.__gender
    
    # 测试
    
    >>> bart = Student('Bart','male')
    >>> if bart.get_gender() != 'male':
    ...     print('测试失败~!')
    ... else:
    ...     bart.set_gender('female')
    ...     if bart.get_gender() != 'female':
    ...         print('测试失败!')
    ...     else:
    ...         print('测试成功~!')
    ...
    测试成功~!
    
    

    以为是多态,然而是多态,更不止是多态, 只要有 run 方法的 对象 都可以 往里丢 ,这一点注意区分 java 的 接口以及父类

    >>> class Animal(object):
    ...     def run(self):
    ...         print('animal is running...')
    ...
    >>> class Dog(Animal):
    ...     def run(self):
    ...         print('dog is running...')
    ...
    >>> def run_twice(animal):
    ...     animal.run()
    ...     animal.run()
    ...
    >>> run_twice(Animal())
    animal is running...
    animal is running...
    >>> run_twice(Dog())
    dog is running...
    dog is running...
    
    # 逝者如斯,东流不回 ,水不继承自 Animal 类 依旧可以 往 run_twice 这个方法里丢, 在 java 里是编译错误!!!
    >>> class water(object):
    ...     def run(self):
    ...         print('water is running....and never back...')
    ...
    >>> run_twice(water())
    water is running....and never back...
    water is running....and never back...
    

    类型判断 type vs isinstance ==》 isinstance 胜 !!! 总是优先使用 isinstance 判断

    >>> type(123) == int
    True
    >>> isinstance(123,int)
    True
    
    下面这种判断太过于复杂
    判断基本数据类型可以直接写int,str等,但如果要判断一个对象是否是函数怎么办?可以使用types模块中定义的常量:
    
    >>> import types
    >>> def fn():
    ...     pass
    ...
    >>> type(fn)==types.FunctionType
    True
    >>> type(abs)==types.BuiltinFunctionType
    True
    >>> type(lambda x: x)==types.LambdaType
    True
    >>> type((x for x in range(10)))==types.GeneratorType
    True
    
    并且还可以判断一个变量是否是某些类型中的一种,比如下面的代码就可以判断是否是list或者tuple:
    
    >>> isinstance([1, 2, 3], (list, tuple))
    True
    >>> isinstance((1, 2, 3), (list, tuple))
    True
    总是优先使用isinstance()判断类型,可以将指定类型及其子类“一网打尽”。
    
    
    # dir 查看,然后等价
    >>> len('ABC')                                                                                                          3                                                                                                                       >>> dir('ABC')                                                                                                          ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill'] 
    
    # 创建自己的 len 方法, 自己写一个 __len__()  方法就是了
    >>> class myStr():
    ...     def __init__(self,val):
    ...         self.__val = val
    ...     def __len__(self):
    ...         return len(self.__val)
    ...
    >>> myStr('abc')
    <__main__.myStr object at 0x02F363D0>
    >>> len(myStr('abc'))
    3
    >>>
    
    # 查看 python 内建函数
    
    >>> dir(__builtins__)
    ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '_', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
    
    # 查看一波
    >>> 'hasattr' in dir(__builtins__)
    True
    >>> 'getattr' in dir(__builtins__)
    True
    >>>
    
    小结
    通过内置的一系列函数,我们可以对任意一个Python对象进行剖析,拿到其内部的数据。要注意的是,只有在不知道对象信息的时候,我们才会去获取对象信息。如果可以直接写:
    
    sum = obj.x + obj.y
    就不要写:
    
    sum = getattr(obj, 'x') + getattr(obj, 'y')
    一个正确的用法的例子如下:
    
    def readImage(fp):
        if hasattr(fp, 'read'):
            return readData(fp)
        return None
    假设我们希望从文件流fp中读取图像,我们首先要判断该fp对象是否存在read方法,如果存在,则该对象是一个流,如果不存在,则无法读取。hasattr()就派上了用场。
    
    请注意,在Python这类动态语言中,根据鸭子类型,有read()方法,不代表该fp对象就是一个文件流,它也可能是网络流,也可能是内存中的一个字节流,但只要read()方法返回的是有效的图像数据,就不影响读取图像的功能。
    
    

    getter setter

    >>> class Student(object):
    ...     def __init__(self,name,*args,**kw):
    ...         self.__name = name
    ...         for arg in args:
    ...               print('arg: {}'.format(arg))
    ...         for key in kw:
    ...               if key == 'city':
    ...                   print('city %s' %kw[key])
    ...     @property
    ...     def score(self):
    ...         return  self._score
    ...     @score.setter
    ...     def score(self,value):
    ...         self._score = value
    ...
    >>> s = Student()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: __init__() missing 1 required positional argument: 'name'
    >>> s = Student('frank',*(1,2,'a',3),**{'city':'changsha','job':'unknown'})
    arg: 1
    arg: 2
    arg: a
    arg: 3
    city changsha
    >>> s.score = 80
    >>> s.score
    80
    
    
    >>> class Screen(object):
    ...     @property
    ...     def width(self):
    ...         return self._width
    ...     @width.setter
    ...     def width(self,width):
    ...          self._width = width
    ...     @property
    ...     def height(self):
    ...          return self._height
    ...     @height.setter
    ...     def height(self,height):
    ...          self._height = height
    ...     @property
    ...     def resolution(self):
    ...          self._resolution = self._width * self._height
    ...          return self._resolution
    ...
    >>> s = Screen()
    >>> s.width = 600
    >>> s.height = 800
    >>> s.resolution
    480000
    
    

    记住标准写法就好,别追问,会晕!!!

    >>> class Student(object):
    ...      def __init__(self,name,score,*args,**kw):
    ...           self._name = name
    ...           self._score = score
    ...           if len(args)!=0:
    ...               self.arg = args[0]
    ...           for key in kw:
    ...               if key == 'city':
    ...                   self.city = kw[key]
    ...      @property
    ...      def name(self):
    ...          return self._name
    ...      @name.setter
    ...      def name(self,name):
    ...          self._name = name
    ...      @property
    ...      def score(self):
    ...           return self._score
    ...      @score.setter
    ...      def score(self,score):
    ...           self._score = score
    ...
    >>> args=('a',1,2)
    >>> kw = {'city':'changsha','job':'unknown'}
    >>> s = Student('frank',100,*args,**kw)
    >>> s.name
    'frank'
    >>> s.score
    100
    >>> s.city
    'changsha'
    >>> s.arg
    'a'
    
    
    
    
    >>> class Student(object):
    ...     def __init__(self,name,age,score,*args,**kw):
    ...         self._name=name
    ...         self._age = age
    ...         self._score = score
    ...         if len(args)!=0:
    ...             self.arg = args[0]
    ...         for key in kw:
    ...             if key == 'city':
    ...                 self.city = kw[key]
    ...     @property
    ...     def name(self):
    ...         return self._name
    ...     @name.setter
    ...     def name(self,name):
    ...         self._name = name
    ...     @property
    ...     def age(self):
    ...         return self._age
    ...     @age.setter
    ...     def age(self,age):
    ...         if not isinstance(age,int):
    ...             raise TypeError('年龄必须为整数!')
    ...         else:
    ...             self._age = age
    ...     @property
    ...     def score(self):
    ...         return self._score
    ...     @score.setter
    ...     def score(self,score):
    ...         if not isinstance(score,int):
    ...             raise TypeError('分数应该为整数!')
    ...         elif not  0<= score <= 100:
    ...             raise ValueError('分数必须介于0-100之间!')
    ...         else:
    ...             self._score = score
    ...
    >>> s = Student('frank',18,100)
    >>> s.name
    'frank'
    >>> s.age
    18
    >>> s.score
    100
    
    
    

    多继承 ,对应 java extends class implements Runnable 这种写法, 只是 python 木有 接口一说 貌似,我也不确定哈,自己去查查吧

    >>> class Animal():
    ...     pass
    ...
    >>> Animal()
    <__main__.Animal object at 0x008DCF30>
    >>> class Mammal(Animal):
    ...     pass
    ...
    >>> class Runnable(object):
    ...     def run(self):
    ...          print('running......')
    ...
    >>> class Flyable(object):
    ...     def fly(self):
    ...         print('flying......')
    ...
    >>> class Dog(Mammal,Runnable):
    ...     pass
    ...
    >>> d = Dog()
    >>> d.run()
    running......
    >>> class Bat(Mammal,Flyable):
    ...     pass
    ...
    ...
    >>> b = Bat()
    >>> b.fly()
    flying......
    

    定制类

    # __slot__  固定 self  属性个数
    # __str__   区别 于  __repr__   前一个 是 返回给 用户的 , 第二个 是 返回给 程序员 用来调试的 
    >>> class Student(object):
    ...      def __init__(self,name):
    ...           self.name = name
    ...      def __str__(self):
    ...           return 'Student object (name = {})'.format(self.name)
    ...      __repr__ = __str__
    ...
    >>> s = Student('frank')
    >>> s
    Student object (name = frank)
    
    

    枚举类

    >>> from enum import Enum
    >>> Month = Enum('Month',('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
    >>> for name,member in Month.__members__.items():
    ...     print(name, '=>', member, ',', member.value)
    ...
    Jan => Month.Jan , 1
    Feb => Month.Feb , 2
    Mar => Month.Mar , 3
    Apr => Month.Apr , 4
    May => Month.May , 5
    Jun => Month.Jun , 6
    Jul => Month.Jul , 7
    Aug => Month.Aug , 8
    Sep => Month.Sep , 9
    Oct => Month.Oct , 10
    Nov => Month.Nov , 11
    Dec => Month.Dec , 12
    >>> from enum import Enum,unique
    >>> @unique
    ... class Weekday(Enum):
    ...     Sun=0
    ...     Mon=1
    ...     Tue=2
    ...     Wed=3
    ...     Thu=4
    ...     Fri=5
    ...     Sat =6
    ...
    >>> day1 = Weekday.Sun
    >>> day1
    <Weekday.Sun: 0>
    >>> day1.value
    0
    >>> day1 = Weekday(0)
    >>> day1
    <Weekday.Sun: 0>
    >>> day1.value
    0
    
    >>> for name,member in Weekday.__members__.items():
    ...     print(name,'==>',member)
    ...
    Sun ==> Weekday.Sun
    Mon ==> Weekday.Mon
    Tue ==> Weekday.Tue
    Wed ==> Weekday.Wed
    Thu ==> Weekday.Thu
    Fri ==> Weekday.Fri
    Sat ==> Weekday.Sat
    

    枚举类与错误综合小例子

    >>> class Student(object):
    ...     def __init__(self,name,gender):
    ...          if not isinstance(gender,Gender):
    ...               raise TypeError('{}'.format('传入的性别类型异常'))
    ...          self.__name = name
    ...          self.gender = gender
    ...
    >>> bart = Student('Bart', Gender.Male)
    >>> if bart.gender == Gender.Male:
    ...     print('测试通过!')
    ... else:
    ...     print('测试失败!')
    ...
    测试通过!
    >>> bart = Student('Bart', '男')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 4, in __init__
    TypeError: 传入的性别类型异常
    >>>
    

    元类,我服了!!!

    推荐一篇高分文章读懂元类

    >>> def fn(self,world = 'world!'):
    ...     print('hello {}'.format(world))
    ...
    >>> Hello = type('Hello',(object,),dict(hello = fn))
    >>> h = Hello()
    >>> h.hello()
    hello world!
    
    
    >>> class ListMetaclass(type):
    ...     def __new__(cls,name,bases,attrs):
    ...         attrs['add']=lambda self,value:self.append(value)
    ...         return type.__new__(cls,name,bases,attrs)
    ...
    >>> class MyList(list,metaclass=ListMetaclass):
    ...     pass
    ...
    >>> l = MyList()
    >>> l.add(5)
    >>> l
    [5]
    
    # 类是一种特殊的对象,因为python 是动态语言,可以后期绑定属性方法等
    
    >>> class ObjectCreator():
    ...     pass
    ...
    >>> print(ObjectCreator)
    <class '__main__.ObjectCreator'>
    >>> print(hasattr(ObjectCreator,'new_attribute'))
    False
    >>> ObjectCreator.new_attribute = 'foo'
    >>> print(hasattr(ObjectCreator,'new_attribute'))
    True
    >>> ObjectCreatorMirror = ObjectCreator
    >>> print(ObjectCreatorMirror())
    <__main__.ObjectCreator object at 0x00859A30>
    
    

    异常处理

    >>> def div(a,b):
    ...     if not isinstance(a,int) or not isinstance(b,int):
    ...         raise TypeError('本方法中除数与被除数都要为整数!')
    ...     try:
    ...         r = a/b
    ...         print('r: {}'.format(r))
    ...     except ZeroDivisionError as e:
    ...         print('except: ',e)
    ...     finally:
    ...         print('finally...')
    ...     print('END...')
    
    >>> r = div(1,2)
    r: 0.5
    finally...
    END...
    >>> div(1,0)
    except:  division by zero
    finally...
    END...
    
    
    >>> def foo(i):
    ...     return 10/i
    ...
    >>> def bar(j):
    ...     return foo(j) *2
    
    >>> def main(n):
    ...     try:
    ...         bar(n)
    ...     except ZeroDivisionError as e:
    ...         logging.exception(e)
    ...     finally:
    ...         print('end...')
    ...
    >>> main(5)
    end...
    >>> main(0)
    ERROR:root:division by zero
    Traceback (most recent call last):
      File "<stdin>", line 3, in main
      File "<stdin>", line 2, in bar
      File "<stdin>", line 2, in foo
    ZeroDivisionError: division by zero
    end...
    
    
    改错:
    
    from functools import reduce
    
    def str2num(s):
        try:
            r = int(s)
        except ValueError as e:
            if isinstance(s,str):
                s=s.replace('.','')
                r = int(s)
            else:
                raise ValueError('传入的不是字符串!')
        finally:
            pass
        return int(s)
    
    def calc(exp):
        ss = exp.split('+')
        ns = map(str2num, ss)
        return reduce(lambda acc, x: acc + x, ns)
    
    def main():
        r = calc('100 + 200 + 345')
        print('100 + 200 + 345 =', r)
        r = calc('99 + 88 + 7.6')
        print('99 + 88 + 7.6 =', r)
    
    main()
    
    
    

    既然如此重要,再谈元类

    # 定义一个函数,用来待会儿在 类 内部或绑定,或调用
    def print_s(s):
        print(s)
    
    
    # 定义元类, 必须继承自 type 才可以被当做元类,被反射
    class ObjectCreatorMetaClass(type):
        def __new__(current_class_name,class_tobe_created_name,base_classess_name_tuple,attrs_hold_dict):
            # 打印一波传进来的参数会发现基本跟命名一致
            print_s('current_class_name: {}'.format(current_class_name))
            print_s('class_tobe_created_name: {}'.format(class_tobe_created_name))
            print_s('base_classess_name_tuple: {}'.format(base_classess_name_tuple))
            print_s('attrs_hold_dict: {}'.format(attrs_hold_dict))
            
            
            #为要被创建的类 ObjectCreator 添加方法,属性都可以
            attrs_hold_dict['flag'] = True
            attrs_hold_dict['current_class_name_print'] = print_s(current_class_name)
            attrs_hold_dict['class_tobe_created_name_print'] = print_s(class_tobe_created_name)
            attrs_hold_dict['base_classess_name_tuple_print'] = print_s(base_classess_name_tuple)
            attrs_hold_dict['attrs_hold_dict_print'] = print_s(attrs_hold_dict)
            return type.__new__(current_class_name,class_tobe_created_name,base_classess_name_tuple,attrs_hold_dict)
    
    # 定义我们要被创建的 类,为了方便查看传进去的 base_classess_name_tuple ,我们手动让他继承一下 object
    class ObjectCreator(object,metaclass = ObjectCreatorMetaClass):
            pass
        
    # 思考为什么 第一次打印时候 attrs_hold_dict 会比后一次 打印 少掉一部分属性,方法 (如 'current_class_name_print': None, 'flag': True)
    # 因为这在传进来时候并没有绑定这些参数方法啊,是后面代码 手动绑定的啦 哈哈哈哈或或或
    
    #  上面的理解有点偏差,但愿看到的人能够自己找出,下面是我重新理解的 
    # 定义一个函数,用来待会儿在 类 内部或绑定,或调用
    def print_s(s):
        print(s)
        return s
    
    #必须继承自 type 才可以被当做元类,被反射
    class ObjectCreatorMetaClass(type):
        def __new__(current_class_name,class_tobe_created_name,base_classess_name_tuple,attrs_hold_dict):
            # 打印一波传进来的参数会发现基本跟命名一致
            print_s('current_class_name: {}'.format(current_class_name))
            print_s('class_tobe_created_name: {}'.format(class_tobe_created_name))
            print_s('base_classess_name_tuple: {}'.format(base_classess_name_tuple))
            print_s('attrs_hold_dict: {}'.format(attrs_hold_dict))
            
            
            #为要被创建的类 ObjectCreator 添加方法,属性都可以
            attrs_hold_dict['flag'] = True
            attrs_hold_dict['get_metaclass'] = print_s(current_class_name)
            attrs_hold_dict['get_tobe_created_class'] = print_s(class_tobe_created_name)
            attrs_hold_dict['get_bases_classess_tuple'] = print_s(base_classess_name_tuple)
            attrs_hold_dict['get_attrs_hold_dict'] = print_s(attrs_hold_dict)
            return type.__new__(current_class_name,class_tobe_created_name,base_classess_name_tuple,attrs_hold_dict)
    
    class ObjectCreator(object,metaclass = ObjectCreatorMetaClass):
            pass
        
    # 思考为什么 第一次打印时候 attrs_hold_dict 会比后一次 打印 少掉一部分属性,方法 (如 'current_class_name_print': None, 'flag': True)
    # 因为这在传进来时候并没有绑定这些参数方法啊,是后面代码 手动绑定的啦 哈哈哈哈或或或
    
    object_from_objectcreator = ObjectCreator()
    print(object_from_objectcreator.flag)
    
    
    # 实际上这里返回了
    object_from_objectcreator.get_metaclass
    object_from_objectcreator.get_tobe_created_class
    object_from_objectcreator.get_bases_classess_tuple
    object_from_objectcreator.get_attrs_hold_dict
    
    
    # out:
    # current_class_name: <class '__main__.ObjectCreatorMetaClass'>
    # class_tobe_created_name: ObjectCreator
    # base_classess_name_tuple: (<class 'object'>,)
    # attrs_hold_dict: {'__qualname__': 'ObjectCreator', '__module__': '__main__'}
    # <class '__main__.ObjectCreatorMetaClass'>
    # ObjectCreator
    # (<class 'object'>,)
    # {'get_bases_classess_tuple': (<class 'object'>,), '__qualname__': 'ObjectCreator', 'get_metaclass': <class '__main__.ObjectCreatorMetaClass'>, '__module__': '__main__', 'get_tobe_created_class': 'ObjectCreator', 'flag': True}
    # True
    # {'__module__': '__main__',
    #  '__qualname__': 'ObjectCreator',
    #  'flag': True,
    #  'get_attrs_hold_dict': {...},
    #  'get_bases_classess_tuple': (object,),
    #  'get_metaclass': __main__.ObjectCreatorMetaClass,
    #  'get_tobe_created_class': 'ObjectCreator'}
    
    
    # 到目前为止,我认为元类来创建 类 ,然后 类再创建对象的过程
    # 应该是 定义一个元类继承 type 这个 class  然后 覆写它的 __new__ 方法, TBD。。。
    
    # 曾经沧海,写完下面这个自动转换要被创建的类的属性为大写 , 元类也就会了
    
    class Upper_attr(type):
        def __new__(cls,name,bases,attr_dict):
            attr_dict = dict( (name.upper(),value)  for name,value in attr_dict.items() if not name.startswith('__'))
            print(attr_dict)
            return super(Upper_attr,cls).__new__(cls,name,bases,attr_dict)
        
    class Foo(object,metaclass = Upper_attr):
        bar = 'bip'
        pass
    
    hasattr(Foo,'BAR')
    {'BAR': 'bip'}
    True
    
    
    # 思考为什么 构造函数 __init__ 不能用 lambda 来写函数体 , 因为,lambda 冒号后边必须接的是一个 表达式而非语句
    def __init__(self, x):
        self.x = x
    
    def printX(self):
        print(self.x)
    
    Test = type('Test', (object,), {'__init__': __init__, 'printX': printX})
    class TestMetaclass(type):
        def __new__(cls,name,bases,attr_dict):
            attr_dict['__init__'] = __init__
            attr_dict['printX']= lambda self:print(self.x)
            return super(TestMetaclass,cls).__new__(cls,name,bases,attr_dict)
        
    class Test(object,metaclass = TestMetaclass):
        pass
    
    Test('123').printX()
    

    IO , 文件 , 内存, 字符,字节 类似于 java 的 IO

    import os
    file_list = os.listdir('.')
    for file in file_list:
        file_name,file_extension = os.path.splitext(file)
        if file_extension == '.csv':
            try:
                f = open(file,'r')
                print(f.read())
                print('file name: ',file_name+file_extension)
            except IOError as ioe:
                print(e)
            finally:
                if f:
                    f.close()
                
            print(file_name,'<----->',file_extension)
    
    
    gender,age,drug,complication
    0,1,3,5
    1,3,2,3
    0,5,1,2
    0,2,3,3
    1,7,3,2
    0,6,3,4
    

    file name: mock_data.csv
    mock_data <-----> .csv

    加上 编码,解码方式

    file_list = os.listdir('.')
    kw = {'encoding':'utf8'}
    for file in file_list:
        file_name,file_extension = os.path.splitext(file)
        if file_extension == '.csv':
            try:
                f = open(file,'r',**kw)
                print(f.read())
                print('file name: ',file_name+file_extension)
            except IOError as ioe:
                print(e)
            finally:
                if f:
                    f.close()
                
            print(file_name,'<----->',file_extension)
    
    
    file_list = os.listdir('.')
    kw = {'encoding':'utf8'}
    for file in file_list:
        file_name,file_extension = os.path.splitext(file)
        if file_extension == '.csv':
            try:
                f = open(file,'r',**kw)
    #             print(f.read())
                for line in f.readlines():
                    print(line)
                print('file name: ',file_name+file_extension)
            except IOError as ioe:
                print(e)
            finally:
                if f:
                    f.close()
                
            print(file_name,'<----->',file_extension)
    
    
    # 使用 with 表达式,相当于 java 中的 try(Autoclosable Resources)   语法糖,自动关闭资源
    
    file_list = os.listdir('.')
    kw = {'encoding':'utf8','errors':'ignore'}
    for file in file_list:
        file_name,file_extension = os.path.splitext(file)
        if file_extension == '.csv':
            with open(file,'r',**kw) as f:
                for line in f.readlines():
                    print(line.strip()) # 去掉末尾的换行符
                
            print(file_name,'<----->',file_extension)
    
    # 读写二进制文件 是不能加 errors 参数的
    >>> with open('9.jpg','rb',errors='ignore') as fr:
    ...     with open('99.jpg','wb') as fw:
    ...          for line in fr.readlines():
    ...              fw.write(line)
    ...
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: binary mode doesn't take an errors argument
    
    # StringIO , python 3 中 是 from io import StringIO ,内存读写
    # 方式一:
    f = StringIO()
    f.write('Hello
    World!
    ')
    print(f.getvalue())
    
    # 方式二:
    from io import StringIO
    f = StringIO('Hello
    World!
    ')
    # print(f.getvalue())
    while True:
        s = f.readline()
        if s == '':
            break
        print(s.strip())
    
    #  StringIO操作的只能是str,如果要操作二进制数据,就需要使用BytesIO。
    
    #  BytesIO实现了在内存中读写bytes,我们创建一个BytesIO,然后写入一些bytes:
    
    from io import BytesIO
    f = BytesIO()
    f.write('中文'.encode('utf-8'))
    print(f.getvalue())
    结果:
    
    b'xe4xb8xadxe6x96x87'
    
    # 解码:
    from io import BytesIO
    f = BytesIO(b'xe4xb8xadxe6x96x87')
    bcontent = f.read()
    print(bcontent.decode('utf-8'))
    与上一种utf-8 编码相反,用 utf-8 解码, 结果如下:
    '中文'
    

    文件夹目录以及文件相关操作

    # 在当前路径下查找包含指定字符串的 所有文件名,并返回。如果是子目录,需要用到递归,没有写,有空写写
    import os
    def search_file(filename):
        return [file for file in os.listdir('.') if os.path.isfile(file) and filename in file]
    
    for name in search_file('并'):
        print(name)
    并发症逻辑回归准确率.ipynb
    并发症概率模型.ipynb
    
    # api 集中:
    os.path.isdir(x)
    os.listdir('.')
    os.path.isfile(x)
    os.path.splitext(x)[1]=='.py'
    os.name # 操作系统类型   nt 
    os.uname() # 注意uname()函数在Windows上不提供,也就是说,os模块的某些函数是跟操作系统相关的。
    os.environ # 在操作系统中定义的环境变量,全部保存在os.environ这个变量中,可以直接查看:
    os.environ.get('PATH')
    # 查看当前目录的绝对路径:
    >>> os.path.abspath('.')
    '/Users/michael'
    # 在某个目录下创建一个新目录,首先把新目录的完整路径表示出来:
    >>> os.path.join('/Users/michael', 'testdir')
    '/Users/michael/testdir'
    # 然后创建一个目录:
    >>> os.mkdir('/Users/michael/testdir')
    # 删掉一个目录:
    >>> os.rmdir('/Users/michael/testdir')
    # 对文件重命名:
    >>> os.rename('test.txt', 'test.py')
    # 删掉文件:
    >>> os.remove('test.py')
    >>> os.path.split('/Users/michael/testdir/file.txt')
    ('/Users/michael/testdir', 'file.txt')
    
    但是复制文件的函数居然在os模块中不存在!原因是复制文件并非由操作系统提供的系统调用。理论上讲,我们通过上一节的读写文件可以完成文件复制,只不过要多写很多代码。
    
    幸运的是shutil模块提供了copyfile()的函数,你还可以在shutil模块中找到很多实用函数,它们可以看做是os模块的补充。
    
    

    序列化 (内存流向磁盘的过程)与 反序列化(磁盘流向内存的过程)

    # 序列化
    import pickle
    person = {'name':'Bob','age':18,'gender':'Male'}
    d = pickle.dumps(person)
    with open('dump.txt','wb') as fw:
        pickle.dump(d,fw)
    # 反序列化
    with open('dump.txt','rb') as fr:
        d=pickle.load(fr)
        print(d)
    

    序列化为json 串存储到磁盘, 反序列化从磁盘读取 json 串到内存转化为python对象

    import json
    person = dict(name = 'Tom',age = 18,gender='Male')
    #  dumps 将dict 转成 json 字符串
    j = json.dumps(person)
    with open('json.txt','w') as fw:
        # dump 序列化 json 串为文件或类文件对象 (file-like Object)
        json.dump(j,fw)
    
    # loads 方法将 json串反序列化
    json.loads(j)
    with open('json.txt','r') as fr:
        # load 方法将从文件中读取字符串并反序列化为json 串,同时你会发现是反序的
        k = json.load(fr)
        print(k)
    
    

    再进一阶,序列化与反序列化 json 串 between 对象

    import json
    class Student(object):
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
            
    s = Student('Tom',18,'Male')
    def student2str(std):
        return dict(name=std.name,age=std.age,sex=std.sex)
    json.dumps(student2str(s))
    json.dumps(s,default=lambda obj:obj.__dict__)
    
    '{"sex": "Male", "age": 18, "name": "Tom"}'
    
    #将上面的 json 字符串转换为 Student 对象
    json_str = '{"sex": "Male", "age": 18, "name": "Tom"}'
    def dict2student(d):
        return Student(d['name'],d['age'],d['sex'])
    s = json.loads(json_str,object_hook=dict2student)
    s.name
    
    结果:
    'Tom'
    

    小结

    Python语言特定的序列化模块是pickle,但如果要把序列化搞得更通用、更符合Web标准,就可以使用json模块。

    json模块的dumps()和loads()函数是定义得非常好的接口的典范。当我们使用时,只需要传入一个必须的参数。但是,当默认的序列化或反序列机制不满足我们的要求时,我们#### 又可以传入更多的参数来定制序列化或反序列化的规则,既做到了接口简单易用,又做到了充分的扩展性和灵活性。

    内建模块以及常用第三方模块

    import urllib.request as urllib2
    import random
    ua_list=["Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv2.0.1) Gecko/20100101 Firefox/4.0.1",
            "Mozilla/5.0 (Windows NT 6.1; rv2.0.1) Gecko/20100101 Firefox/4.0.1",
            "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
            "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11"]
    u_agent = random.choice(ua_list)
    # print(u_agent)
    url = 'http://www.baidu.com'
    request = urllib2.Request(url=url)
    request.add_header("User_agent",u_agent)
    response = urllib2.urlopen(request)
    print(response.read())
    

    其他

    标准数据类型
    Python3 中有六个标准的数据类型:
    
    Number(数字)
    String(字符串)
    List(列表)
    Tuple(元组)
    Sets(集合)
    Dictionary(字典)
    Python3 的六个标准数据类型中:
    
    不可变数据(四个):Number(数字)、String(字符串)、Tuple(元组)、Sets(集合);
    可变数据(两个):List(列表)、Dictionary(字典)。
    Set(集合)
    集合(set)是一个无序不重复元素的序列。
    
    基本功能是进行成员关系测试和删除重复元素。
    
    # 字符串的一些内建函数需要掌握 ,首字母大写 capitalize(),lower(),upper() 等等
    a = 'frank'
    a.capitalize()
    
    可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
    
    # set可以进行集合运算
    a = set('abracadabra')
    b = set('alacazam')
     
    print(a)
     
    print(a - b)     # a和b的差集
     
    print(a | b)     # a和b的并集
     
    print(a & b)     # a和b的交集
     
    print(a ^ b)     # a和b中不同时存在的元素
    
    dict_1 = dict(name='frank',age=18)  # 这写法我喜欢
    dict_1 = {'name':'frank','age':18}  # 这写法也能接受
    dict_1 = dict([('name','frank'),('age',18)])   # 这种写法我觉得纯粹是有病。。。
    
    
    删除引用,估算引用,查询引用
    del b
    eval('b') 
    hex(id(b))   # 16 进制 hash值
    # str()出来的值是给人看的。。。repr()出来的值是给python看的,可以通过eval()重新变回一个Python对象
    a = 'a'
    eval('a')
    hex(id(a))
    eval(repr(a))
    
    # print 默认输出是换行的,如果要实现不换行需要在变量末尾加上 end="":
    # 不换行输出
    print( x, end=" " )
    print( y, end=" " )
    dict  items() , keys(), values()
    list  pop , append
    import keyword
    keyword.kwlist
    
    #  dict 是个好命令
    dir(dict)
    '__setitem__',
     '__sizeof__',
     '__str__',
     '__subclasshook__',
     'clear',
     'copy',
     'fromkeys',
    
    


    python 日志

    # 这段代码保存为 config.py
    # -*- coding: utf-8 -*-
    __author__ = 'Frank Li'
    import logging
    class Config():
        # 创建一个logger
        logger = logging.getLogger('statisticNew')
        logger.setLevel(logging.DEBUG)
    
        # 创建一个handler,用于写入日志文件
        fh = logging.FileHandler('test.log')
        fh.setLevel(logging.DEBUG)
    
        # 再创建一个handler,用于输出到控制台
        ch = logging.StreamHandler()
        ch.setLevel(logging.DEBUG)
    
        # 定义handler的输出格式
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        fh.setFormatter(formatter)
        ch.setFormatter(formatter)
    
        # 给logger添加handler
        logger.addHandler(fh)
        logger.addHandler(ch)
        def getLog(self):
            return self.logger
    
    

    引用上段代码保存的额 config.py 文件里的module

    __author__ = 'Frank Li'
    from config import Config
    if __name__ == '__main__':
        conf = Config()
        logger = conf.getLog()
        logger.info('foorbar')
        boy = "Frank Li"
        is_handsome = True
        logger.info("boy=%s,is_handsome=%s",boy,is_handsome)
       
    # 异常处理,以后尽量不要用山寨的 print 了
    
    try:
       ....  
    except Exception as e:
        logger.exception('ERROR readFile:%s,%s' % (path,str(e)))
    

    编码规范 , 变量定义

    #  Python变量命名用法(一般变量、常量、私有变量、内置变量)
    #coding:utf8
    __author__ = "libingxian"
    
    class TestDemo(object):
        """
        Python变量命名用法(以字符或者下划线开头,可以包括字母、数字、下划线,区别大小写)
        一般变量
        常量
        私有变量
        内置变量
        """
        FINAL_VAR = "V1.0" # 常量,不可修改的变量,以大写字母或加下划线命名,这个只是约定,即使更改了也不会报错
    
        class_name = "TestDemo" # 常见变量命名,
    
        __maker__ = 'libingxian' # 内置变量,两个前置下划线和两个后置下划线,内置对象所具有,声明时不可与内置变量名的重复
    
        def __init__(self):
            self.__private_var = "private" # 私有变量,以两个前置下划线开头,只能在本类中使用,类外强制访问会报错
            self.public_var = "public" # 一般变量
    
        def __private_method(self):# 私有方法,以两个下划线开头、字母小写,只能在本类中使用,类外强制访问会报错
            print "i am private"
    
        def public_method(self):
            print "i am public"
    
    test_demo = TestDemo()
    print test_demo.FINAL_VAR # 访问常量
    print test_demo.public_var # 访问一般变量
    print test_demo.__private_var # 访问私有变量,运行会报错
    test_demo.__private_method() # 访问私有方法,运行会报错
    

    字典操作 dict_1.update(dict_2) 合并 dict

    dict_1 = {'name':'Frank','age':18}
    gender_dict = {'gender':'Male'}
    dict_1.update(gender_dict)
    print(dict_1)
    

    字典推导式

    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()
    }
    
    # mcase_frequency == {'a': 17, 'z': 3, 'b': 34}
    
    # key,value 交换
    >>> {value:key for key,value in dict_1.items()}
    {'Frank': 'name', 18: 'age'}
    

    由 两个 list 合并 dict 原理是利用 zip 合并成 ((key1,value1),(key2,value2)) 然后用 dict[key] = value 方式

    list_1 = ['name','age']
    list_2 = ['Frank',18]
    person_dict = {}
    for key,value in zip(list_1,list_2):
        person_dict[key] = value
    print(person_dict)
    
    # 反过来   zip(*zipped)   ==> flattern
    dict_2 = dict(name='Frank',age=18)
    list_3,list_4 = zip(*[ [key,value] for key,value in dict_2.items()])
    list_3,list_4
    
    

    list 去重

    # 方法一 
    l1 = ['b','c','d','b','c','a','a']
    l2 = {}.fromkeys(l1).keys()
    print(l2)
    # 方法二
    l3 = list(set(l1))
    
    # 方法三
    >>> a=[1,2,4,2,4,5,7,10,5,5,7,8,9,0,3]
    >>> a.sort()
    >>> a
    [0, 1, 2, 2, 3, 4, 4, 5, 5, 5, 7, 7, 8, 9, 10]
    >>> last = a[-1]
    >>> for i in range(len(a)-2,-1,-1):
    ...     if last == a[i]:
    ...         del a[i]
    ...     else:
    ...         last = a[i]
    ...
    >>> a
    [0, 1, 2, 3, 4, 5, 7, 8, 9, 10]
    
    # 封装成方法 distinct
    >>> def distinct(lst):
    ...     lst.sort()
    ...     last = lst[-1]  # 这里不正向的原因是lst长度会改变
    ...     for i in range(len(lst)-2,-1,-1): # 倒序来比较列表
    ...         if last == lst[i]:
    ...             del lst[i] # 如果与已经有的值相同则删除
    ...         else:    # 否则则将 last 指向前一个元素
    ...             last = lst[i]
    ...     return lst
    distinct([1,2,4,2,4,5,7,10,5,5,7,8,9,0,3])
    
    
    # 三元运算  还可以用 元组条件表达式的三元运算   is_fat =('not fat','fat') [is_state]
    >>> is_state = True
    >>> is_fat = 'fat' if is_state else 'not fat'
    >>> is_fat
    'fat'
    
    # 优雅地查出重复数据
    >>> str_list = ['a','b','a','c','d','b','c']
    >>> [s for s in str_list if str_list.count(s) >1]
    ['a', 'b', 'a', 'c', 'b', 'c']
    >>> set([s for s in str_list if str_list.count(s) >1])
    {'a', 'c', 'b'}
    
    # 求交集 差集
    >>> str_list2 = ['a','b']
    >>> str_list = set([s for s in str_list if str_list.count(s) >1])
    >>> str_list.intersection(str_list2)
    {'a', 'b'}
    >>> str_list.difference(str_list2)
    {'c'}
    

    列表排序

    列表排序
    
        a = [(1, 2), (4, 1), (9, 10), (13, -3)]
        a.sort(key=lambda x: x[1])
    
        print(a)
        # Output: [(13, -3), (4, 1), (1, 2), (9, 10)]
    

    列表并行排序

    list_1 = [8,4,3,2,7,6,5]
    list_2 = ['e','d','c','y','i','o','p']
    data = zip(list_1,list_2)
    data = sorted(data)
    list1, list2 = map(lambda t: list(t), zip(*data))
    print(list1)
    print(list2)
    

    模拟 with open

    >>> 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):
    ...        self.file_obj.close()
    ...
    >>> with File('C:/Users/FrankLi/Desktop/Demo.java','r') as f:
    ...     for line in f.readlines():
    ...         print(line)
    ...
    class Demo{
    
            public static void main(String[] args){
    
                    System.out.println("Hello world!");
    
            }
    
    }
    我们的__exit__函数接受三个参数。这些参数对于每个上下文管理器类中的__exit__方法都是必须的。我们来谈谈在底层都发生了什么。
    
    with语句先暂存了File类的__exit__方法
    然后它调用File类的__enter__方法
    __enter__方法打开文件并返回给with语句
    打开的文件句柄被传递给opened_file参数
    我们使用.write()来写文件
    with语句调用之前暂存的__exit__方法
    __exit__方法关闭了文件
    

    类似于 scala 的 flattern 列表展平

    >>> import itertools
    >>> a_list = [[1,2],[3,4],[5,6]]
    >>> print(itertools.chain(*a_list))
    <itertools.chain object at 0x039E6090>
    >>> print(list(itertools.chain(*a_list)))
    [1, 2, 3, 4, 5, 6]
    >>> print(list(itertools.chain.from_iterable(a_list)))
    [1, 2, 3, 4, 5, 6]
    
    >>> l = [[1,2,3],[4,5,6], [7], [8,9]]
    >>> [item for sublist in l for item in sublist] # 推导式中两层 for 循环也可以实现
    [1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    

    for - else 结构

    for n in range(2, 100):
        for x in range(2, n):
            if n % x == 0:
                print(n, 'equals', x, '*', n / x)
                break
        else:
            # loop fell through without finding a factor
            print(n, 'is a prime number')
    
    # 替代 switch case 方案 字典映射
    >>> def switch(x):
    ...     return {'0':0,'1':1,'2':2}.get(x,'nothing')
    ...
    >>> switch('0')
    0
    >>> switch('3')
    'nothing'
    

    16.检查一个字符串是否是一个数字?

    In[22]: x = '569789'
    
    In[23]: x.isdigit()
    
    Out[23]: True
    
    In[24]: y = 'gdf2667'
    
    In[25]: y.isdigit()
    
    Out[25]: False
    
    

    17.查找列表中某个元素的下标?

    In[26]: ['a','b','c'].index('b')
    
    Out[26]: 1
    

    18.如何在列表中随机取一个元素?

    import random
    
    f= ['a', 'b', 'c']
    
    print(random.choice(f))
    
    
    # 字典排序
    >>> dict_1 = {'a':3,'b':1,'c':2}
    >>> sorted(dict_1.items(),key=lambda x:x[1])
    [('b', 1), ('c', 2), ('a', 3)]
    
    >>> import operator
    >>> file_dict={"a":1,"b":2,"c":3}
    >>> sorted(file_dict.items(),key = operator.itemgetter(1),reverse=True)
    [('c', 3), ('b', 2), ('a', 1)]
    
    
    # 字符串的不可变形 = immutability
    Str1 = 'Yuxl'
    print(Str1)
    try:
        Str1[0] = 'XX'
    except:
        print("不可更改")
    Yuxl
    不可更改
    
    >>> import random
    >>> def g_rand_range(max):
    ...     for i in range(1,max+1,1):
    ...         yield random.randint(1,10)
    ...
    >>> for i in g_rand_range(10):
    ...     print(i)
    
    

    别人的总结图

    Python 基础知识总结图

    JAVA vs PYTHON (还没细看)

    jvsp

    总结:

    至此,关于 python 基础的总结基本完结,其中有涉及到高阶知识 , 元类,位置参数关键字参数 可变参数(*args type: tuple,**kwargs type: dict),
    生成器,装饰器,函数式编程风格的 map reduce filter sorted上下文管理器, 要补充的有 : 进程线程协程,异步io
    接下来的时间应该是 学习 python 的重要常用模块(Pandas,Numpy,Scipy,PIL pillow , opencv,sk-learn,xgboost,爬虫库 scrappy等)以及框架(Django)

    最后感慨一下,如果一开始碰到了python 也许根本就不会去学java了,感觉python的设计思想比较符合我的思想各种黑魔法的魅力吸引着我!!!
    (虽然java不可否认也是一门优雅的工程化设计语言但不够精简,语法冗长)。。。life is short , I use python and java ! 其实语言本身没有好坏,
    只有适用场景(多一门语言能力便多一种工具,而工具可以提高效率!),

    每一门语言都有自己的设计思想,一个合格的程序员应该多学几门语言,了解怎样用不同的方法和思维去解决同一个问题。因此学习多门并不仅仅是为了更好的装逼!!!

    我曾经还一直在想为什么没有出现一门语言一统天下呢 现在想想也是天真。。。
    不过语言始终流于招式,接下来是要修炼一波内功了,算法才是灵魂!

    如果有来生,一个人去远行,看不同的风景,感受生命的活力。。。
  • 相关阅读:
    poj 2411 Mondriaan's Dream 骨牌铺放 状压dp
    zoj 3471 Most Powerful (有向图)最大生成树 状压dp
    poj 2280 Islands and Bridges 哈密尔顿路 状压dp
    hdu 3001 Travelling 经过所有点(最多两次)的最短路径 三进制状压dp
    poj 3311 Hie with the Pie 经过所有点(可重)的最短路径 floyd + 状压dp
    poj 1185 炮兵阵地 状压dp
    poj 3254 Corn Fields 状压dp入门
    loj 6278 6279 数列分块入门 2 3
    VIM记事——大小写转换
    DKIM支持样本上传做检测的网站
  • 原文地址:https://www.cnblogs.com/Frank99/p/9111124.html
Copyright © 2011-2022 走看看