• python复习之中级


    一、函数

    A、函数介绍

    a.1、什么是函数

    • 函数就是抽象计算过程,调用相应的函数,返回结果;

    a.2、内置函数

    • map
    def f(x):
        return x*x
    print map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])

    reduce()

    def prod(x, y):
        return x*y
    print reduce(prod, [2, 4, 5, 7, 12])
    

    filter()

    import math
    
    def is_sqr(x):
        if math.sqrt(x) % 1 == 0:
            return x
        
    print filter(is_sqr, range(1, 101)) #[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
    

    sorted()

    #输入:['bob', 'about', 'Zoo', 'Credit']
    #输出:['about', 'bob', 'Credit', 'Zoo']
    def cmp_ignore_case(s1, s2):
        s1 = s1.upper()
        s2 = s2.upper()
        if s1 < s2:
            return -1
        if s1 > s2:
            return 1
        return 0
    
    print sorted(['bob', 'about', 'Zoo', 'Credit'], cmp_ignore_case)
    

    a.3、定义函数

    • 格式> 
    def function(args):
    	print('Hello %s.' % args)
    
    function('coob')  #Hello coob.
    • 返回值>返回值-返回函数
    def f():
        print 'call f()...'
        # 定义函数g:
        def g():
            print 'call g()...'
        # 返回函数g:
        return g
    
    • 参数: 默认参数 x, 可变参数 *argrs 可传入任意个参数, 字典参数**kwargs;
    • 返回值:return,如果没有return语句,函数执行完毕后也会返回结果,只是结果为 None,return None可以简写为return;

    a.4、闭包

    • 介绍:内层函数引用了外层函数的变量(参数也算变量),然后返回内层函数的情况,称为闭包(Closure)。

    例:

    def calc_sum(lst):
        def lazy_sum():
            return sum(lst)
        return lazy_sum
    
    • 特点:返回的函数还引用了外层函数的局部变量,所以,要正确使用闭包,就要确保引用的局部变量在函数返回后不能变。举例如下:
    #返回闭包不能引用循环变量,请改写count()函数,让它正确返回能计算1x1、2x2、3x3的函数。
    def count():
        fs = []
        for i in range(1, 4):
            def f(j):
                def g():
                    return j*j
                return g
            r = f(i)
            fs.append(r)
        return fs
    
    f1, f2, f3 = count()
    print f1(), f2(), f3()

    a.5、匿名函数

    • 介绍:只能有一个表达式, 
    map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])
    

      示例

    # 利用匿名函数简化以下代码:
    def is_not_empty(s):
        return s and len(s.strip()) > 0
    
    print filter(lambda s: s and len(s.strip()) > 0, ['test', None, '', 'str', '  ', 'END'])
    

    B、装饰器

    b.1、问题:

    • 定义了一个函数,想在运行时动态增加功能,又不想动态改变函数本身的代码,比如说 每次运行函数我都要知道该函数运行花了多长时间,那么就用装饰器吧!
    • 封装、代码复用;
    def new_fn(f):
    	def fn(x):
    		print('call' + f.__name__ + '()')
    		return f(x)
    	return fn 
    @new_fn
    def f1(x):
    	return x*x
    	
    # f1 = new_fn(f1)
    # print(f1(5))
    
    print(f1(3))
    # callf1()
    # 9

    示例一 :

    import time
    def performance(f):
        def fn(*args, **kw):
            t1 = time.time()
            r = f(*args, **kw)
            t2 = time.time()
            print 'call %s() in %fs' % (f.__name__, (t2 - t1))
            return r
        return fn
    
    @performance
    def factorial(n):
        return reduce(lambda x,y: x*y, range(1, n+1))
    print factorial(10)
    

    示例二:

    import time
    
    def performance(unit):
        def a(f):
            def b(*args,**kw):
                t1 = time.time()
                r = f(*args,**kw)
                t2 = time.time()
                t = (t2-t1)*1000 if unit == 'ms' else (t2-t1)
                print'call %s() in %s' % (f.__name__, t)
                return r
            return b
        return a
    
    @performance('ms')
    def factorial(n):
        return reduce(lambda x,y: x*y, range(1, n+1))
    
    print factorial(10)
    

    示例三: @functools.wraps(f)     没有该装饰器对于那些依赖函数名的代码就会失效;

    import time, functools
    
    def performance(unit):
        def a(f):
            @functools.wraps(f)
            def b(*args,**kw):
                t1 = time.time()
                r = f(*args,**kw)
                t2 = time.time()
                t = (t2-t1)*1000 if unit == 'ms' else (t2-t1)
                print'call %s() in %s' % (f.__name__, t)
                return r
            return b
        return a
    
    @performance('ms')
    def factorial(n):
        return reduce(lambda x,y: x*y, range(1, n+1))
    
    print factorial.__name__
    

    C、偏函数  

    c.1、自我理解,即是对原函数的基础上进行改造,让原函数只实现自身某一部分的功能或者类似的功能。

    示例:

    >>> import functools
    >>> int2 = functools.partial(int, base=2)
    >>> int2('1000000')
    64
    >>> int2('1010101')
    85
    

    D、模块

    d.1、介绍

    d.2、包和模块区别

    包就是一个文件件,里面必须要有个 "__init__.py"的文件,目的是将文件夹变为一个Python模块, 

    C、高阶函数

    b.1、递归

    • 递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰;
    • 使用递归函数需要注意防止栈溢出;

     二、类

    A、介绍

    面向对象三大特性(封装、继承、多态)

    B、成员

    b.1、属性

    • __xxx__:如果一个属性以该形式定义,这种定义被称为特殊属性、_xxx:可以在子类中使用、__xxx:不可以在子类中使用(无法被外部访问)
    • 所有实例都可以访问类的属性,并且,所有实例访问的类属性都是同一个!也就是说,实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。 
    class Person(object):
        address = 'Earth'
        def __init__(self, name):
            self.name = name
    
    print Person.address
    # => Earth
    
    • 直接通过类访问,当然实例也是可以直接访问类属性的,
    p1 = Person('Bob')
    p2 = Person('Alice')
    print p1.address
    # => Earth
    print p2.address
    # => Earth
    
    • 由于Python是动态语言,类属性也是可以动态添加和修改的,注意千万不要在实例上修改类属性,它实际上并没有修改类属性,而是给实例绑定了一个实例属性。
    Person.address = 'China'
    print p1.address
    # => 'China'
    print p2.address
    # => 'China'
    

    接收任意额外的关键字参数

    class Person(object):
    
        def __init__(self, name, gender, **kw):
            self.name = name
            self.gander = gender
            for k,v in kw.items():
                setattr(self, k, v)
    
    p = Person('Bob', 'Male', age=18, course='Python')
    print p.age
    print p.course
    

      

      

    b.2、实例方法

    • 实例的方法就是在类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样的:
    • 在实例方法内部,可以访问所有实例属性,这样,如果外部需要访问私有属性,可以通过方法调用获得,这种数据封装的形式除了能保护内部数据一致性外,还可以简化外部调用的难度。
    class Person(object):
    
        def __init__(self, name):
            self.__name = name
    
        def get_name(self):
            return self.__name
    #调用
    p1 = Person('Bob')
    print p1.get_name()  # self不需要显式传入
    # => Bob
    

    b.3、类方法

    • 要在class中定义类方法,需要这么写;
    • 类方法的第一个参数将传入类本身,通常将参数名命名为 cls,上面的 cls.count 实际上相当于 Person.count;
    • 因为是在类上调用,而非实例上调用,因此类方法无法获得任何实例变量,只能获得类的引用;
    class Person(object):
        count = 0
        @classmethod
        def how_many(cls):
            return cls.count
        def __init__(self, name):
            self.name = name
            Person.count = Person.count + 1
    
    print Person.how_many()
    p1 = Person('Bob')
    print Person.how_many()
    
    0
    1

    b.4、调用时不用加()的装饰器

     @property 装饰器:调用时不用加

    b.5、属性和方法总结

    • 普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self
    • 类方法:由调用; 至少一个cls参数;执行类方法时,自动将调用该方法的复制给cls
    • 静态方法:由调用;无默认参数;
    • class Foo:
        
          #静态方法
          @staticmethod
          def xo(arg1, arg2):     #无默认参数,可不传参数,可传任意参数
              print("xo")
        
          #类方法
          @classmethod
          def xxoo(cls):             #定义类方法,至少有一个cls参数
              print(cls)
        
          #普通方法,类中
          def show(self):           #定义普通方法,至少有一个self参数
              print("show")
        
      # 调用静态方法
      Foo.xo(1,2)
        
      # 调用类方法
      Foo.xxoo()
        
      # 调用普通方法
      obj = Foo:
      obj.show()

    C、类的继承

    c.1、示例:

    class Person(object):
        def __init__(self, name, gender):
            self.name = name
            self.gender = gender
    
    • 开始继承  注意:super(子类名, self).__init__(父类属性)的用法 
    class Student(Person):
        def __init__(self, name, gender, score):
            super(Student, self).__init__(name, gender)
            self.score = score
    
    • 一定要用 super(Student, self).__init__(name, gender) 去初始化父类,否则,继承自 Person 的 Student 将没有 name 和 gender。  

      

    使用super()的漂亮之处在于,你不需要明确给出任何基类名字,这意味着如果你改变了类继承关系,你只需要改一行代码(class语句本身)而不必在大量代码中去查找所有被修改的那个类的名字。
    
                                                                             ------《Python核心编程》P358
    

    c.2、python中判断类型

    • 函数isinstance()可以判断一个变量的类型,既可以用在Python内置的数据类型如str、list、dict,也可以用在我们自定义的类,它们本质上都是数据类型。
    • 自我总结,子类属于父类,父类不属于子类;
    class Person(object):
    
        def __init__(self, name, gender):
            self.name = name
            self.gender = gender
    
    class Student(Person):
    
        def __init__(self, name, gender, score):
            super(Student, self).__init__(name, gender)
            self.score = score
    
    class Teacher(Person):
    
        def __init__(self, name, gender, course):
            super(Teacher, self).__init__(name, gender)
            self.course = course
    
    t = Teacher('Alice', 'Female', 'English')
    
    print isinstance(t, Person)  #T
    print isinstance(t, Student) #F
    print isinstance(t, Teacher) #T
    print isinstance(t, object)  #T
    

    c.3、多态

      假如父类与子类都拥有相同的方法,在调用的过程优先使用自己的方法,如果自己没有就使用父类的方法,这种行为我们称之为多态;

    D、特殊方法

    d.1、介绍:

    • 特殊方法定义在class中
    • 不需要直接调用
    • Python的默写函数或操作符会调用对应的特殊方法

    d.2、重写特殊方法:

    • __str__ 与 __repr__ , 后者是在终端下 敲s 结果与 前者一样
    class Person(object):
        def __init__(self, name, gender):
            self.name = name
            self.gender = gender
    
    class Student(Person):
        def __init__(self, name, gender, score):
            super(Student, self).__init__(name, gender)
            self.score = score
        def __str__(self):
            return '(Student: %s, %s, %s)' % (self.name, self.gender, self.score)
        __repr__ = __str__
    
    s = Student('Bob', 'male', 88)
    print s
    #(student: bob, male, 88)
    

      

    E、设置类的一些方法

    d.1、type

    >>> type(123)
    <type 'int'>
    >>> s = Student('Bob', 'Male', 88)
    >>> type(s)
    <class '__main__.Student'>
    

    d.2、 dir() 

    >>> dir(123)   # 整数也有很多属性...
    ['__abs__', '__add__', '__and__', '__class__', '__cmp__', ...]
    
    >>> dir(s)
    ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'gender', 'name', 'score', 'whoAmI']
    

    d.3、filter()

    d.4、getattr()   当name 不存在时,会报错;

    >>> getattr(s, 'name')  # 获取name属性
    'Bob'
    

    d.5、setattr()

    >>> setattr(s, 'name', 'Adam')  # 设置新的name属性
    
    >>> s.name
    'Adam'
    

      

      

     

  • 相关阅读:
    CUDA运行时 Runtime(一)
    CUDA C++程序设计模型
    CUDA C++编程手册(总论)
    深度学习到底有哪些卷积?
    卷积神经网络去雾去雨方法
    马斯克如何颠覆航天? 1/5385成本,c++和python编程!
    CUDA 9中张量核(Tensor Cores)编程
    利用表达式调用全局变量计算出错原因
    述函数的作用,浏览器执行函数的过程
    表达式的差异和相同点
  • 原文地址:https://www.cnblogs.com/learn-python-M/p/7512299.html
Copyright © 2020-2023  润新知