zoukankan      html  css  js  c++  java
  • 面向对象基础

    面向对象编程(Object Oriented Programming,OOP)

    1. 面向过程编程最易被初学者接受,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,即:将之前实现的代码块复制到现需功能处。
    2. Java和C#只支持面向对象编程,而python比较灵活,即支持面向对象编程也支持函数式编程。
    3. 面向对象三大特性:封装继承多态

    一、封装

    封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
    调用被封装的内容时,有两种情况:

    1. 通过对象直接调用
    2. 通过self间接调用
    #1. 通过对象直接调用
    class Foo:
        def __init__(self, name, age):
            self.name = name
            self.age = age
     
    obj1 = Foo('morra', 18)
    print obj1.name    # 直接调用obj1对象的name属性
    print obj1.age     # 直接调用obj1对象的age属性
     
    
    #2. 通过self间接调用
    class Foo:
        def __init__(self, name, age):
            self.name = name
            self.age = age
      
        def detail(self):
            print self.name
            print self.age
      
    obj1 = Foo('morra', 18)
    obj1.detail()  # Python默认会将obj1传给self参数,所以,此时方法内部的 self = obj1
     
    

    综上所述,对于面向对象的封装来说,其实就是使用__init__方法将内容封装到对象中,然后通过对象直接或者self间接获取被封装的内容。

    二、继承

    继承,就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。父类也叫基类,子类也叫派生类。

    class Animals:              #基类
        def __init__(self, name):
            self.name = name
     
        def eat(self):
            pass
     
        def drink(self):
            pass
     
    class Dog(Animals):         #派生类
        def __init__(self, name):
            self.name = name
     
        def bark(self):
            print('汪')
     
     
    obj_dog = Dog('morra')
    obj_dog.eat()
    obj_dog.bark()
    

    (1) 单继承

    优先级是,先子类后父类

    (2) 多继承

    python可以同时继承多个类(C# java是不可以的)。
    优先级是,先子类后父类,父类里面先左再右,广度优先。

    #新式类的广度优先查找
    class D(object):
        def bar1(self):
            print 'D.bar'
     
    class C(D):
        def bar(self):
            print 'C.bar'
     
    class B(D):
        def bar(self):
            print 'B.bar'
     
    class A(B, C):
        def bar(self):
            print 'A.bar'
    a = A()
    # 执行bar方法时
    # 查找顺序:A --> B --> C --> D
    # 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
    a.bar()
    

    (3) 执行父类的构造方法

    #方法一:super,通过python多继承的原则查找
    class Animal:
        def __init__(self):
            print('A构造方法')
            self.ty = "动物"
     
    class Cat(Animal):
        def __init__(self):
            print('B构造方法')
            self.n = "猫"
            super(Cat,self).__init__()  #执行父类的构造方法,推荐用super()
     
    c = Cat()
    print(c.__dict__)
     
    # ---------
    # B构造方法
    # A构造方法
    # {'n': '猫', 'ty': '动物'}
     
     
    #方法二:Animal,直接指定基类(不建议使用)
    class Animal:
        def __init__(self):
            print('A构造方法')
            self.ty = "动物"
     
    class Cat(Animal):
        def __init__(self):
            print('B构造方法')
            self.n = "猫"
            Animal.__init__(self)       #不推荐
     
    c = Cat()
    print(c.__dict__)
     
    # ---------
    # B构造方法
    # A构造方法
    # {'n': '猫', 'ty': '动物'}
    

    三、多态

    Pyhon不支持Java和C#这一类强类型语言中多态的写法,但是原生多态,其Python崇尚“鸭子类型”。

    python的“鸭子类型”:

    class F1:
        pass
     
    class S1(F1):
        def show(self):
            print 'S1.show'
     
    class S2(F1):
        def show(self):
            print 'S2.show'
     
    def Func(obj):
        print obj.show()
     
    s1_obj = S1()
    Func(s1_obj) 
     
    s2_obj = S2()
    Func(s2_obj) 
    

    四、反射在面向对象里的应用

    class Foo:
        def __init__(self,name):
            self.name = name    对象.属性=变量
            pass
     
        def show(self):
            pass
     
     
    obj = Foo('morra')
     
    r = hasattr(Foo, 'show')    #只能找类里的成员
    print(r)  # True
     
    r = hasattr(obj, 'name')   #在对象中可以找自己的属性,就是self.name中的name属性
    print(r)  # True
     
    r = hasattr(obj, 'show')    #对象中也可以找类的成员,是通过python里的类对象指针来实现的
    print(r)  # True
     
    

    m = __import__('s1',fromlist=True)      #通过反射获取模块
     
    class_name = getattr(m,"Foo")       #在模块中获取Foo类
     
    obj = class_name('morra')       #实例化
     
    val = getattr(obj,'name')         #获取类中的name属性
     
    print(val)
    

    五、旧式类与新式类

    旧式类与新式类区别总结:

    1. 在python2.x的版本才有新式类和旧式类之分
    2. 新式类的存在是为了统一类(class)和类型(type)
    3. 旧式类定义class AA,新式类class AA(object)
    4. 在多重继承的查找和调用方法上,旧式类是深度优先,新式类是广度优先
    5. 在python2.x版本中为了确保自己使用的是新式类,有以下方法:
      (a)_metaclass_ = type
      (b)自己的类都从内建类object直接或者间接地继承
    6. 在Python3里面,不存在这些问题了,因为所有的类都是object类的子类(隐式),python3中都是新式类,即使用广度优先的查找方法

    (1) 定义形式

    #python2.7中的旧式类
    class AA():
        pass
     
    a = AA()
    print(type(a))      #<type 'instance'>
    print(type(AA))     #<type 'classobj'>
     
     
    #python2.7中的新式类
    class AA(object):
        pass
     
    a = AA()
    print(type(a))      #<class '__main__.AA'>
    print(type(AA))     #<type 'type'>
     
     
    #python3中的新式类
    class AA(object):
        pass
     
    a = AA()
    print(type(a))      ## <class '__main__.AA'>
    print(type(AA))     # <class 'type'>
    

    (2) 多重继承时的查找规则

    #旧式类的深度优先查找
    class D:
        def bar1(self):
            print 'D.bar'
     
    class C(D):
        def bar(self):
            print 'C.bar'
     
    class B(D):
        def bar(self):
            print 'B.bar'
     
    class A(B, C):
        def bar(self):
            print 'A.bar'
     
    a = A()
    # 执行bar方法时
    # 查找顺序:A --> B --> D --> C
    # 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
    a.bar()
    

    #新式类的广度优先查找
    class D(object):
        def bar1(self):
            print 'D.bar'
     
    class C(D):
        def bar(self):
            print 'C.bar'
     
    class B(D):
        def bar(self):
            print 'B.bar'
     
    class A(B, C):
        def bar(self):
            print 'A.bar'
    a = A()
    # 执行bar方法时
    # 查找顺序:A --> B --> C --> D
    # 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
    a.bar()
    

    六、补充

    (1) isinstance(obj, cls)

    检查是否obj是否是类 cls 的对象

    class Foo(object):
        pass
     
    obj = Foo()
    
    isinstance(obj, Foo)
    

    (2) issubclass(sub, super)

    检查sub类是否是 super 类的派生类

    class Foo(object):
        pass
     
    class Bar(Foo):
        pass
     
    issubclass(Bar, Foo)
    

    (3) __base__父类查询

    用 _base_ 属性来查询某个类的父类

    class father:
        pass
    
    class child(father):
        pass
    print(father)   #<class '__main__.father'>
    print(child.__base__)   #<class '__main__.father'>
    

    (4) __class__查询对象所属的类和类名

    a = [1, 2, 3]
    print(a.__class__)  #<class 'list'>,查询对象所属的类
    print(type(a))      #<class 'list'>
    
    print(a.__class__.__name__)     #list,查询对象所属类的类名
    

    (5) 查询对象的属性

    除了使用dir()来查询对象的属性之外,我们可以使用下面内置(built-in)函数来确认一个对象是否具有某个属性:

    hasattr(obj, attr_name)   # attr_name是一个字符串
    

    例如:

    a = [1,2,3]
    print(hasattr(a,'append')) 
    

    (6) 查询函数的参数

    import inspect
    print(inspect.getargspec(func))
    
  • 相关阅读:
    反向代理实例
    nginx常用命令和配置
    nginx的安装
    Can Live View boot up images acquired from 64bit OS evidence?
    What is the behavior of lnk files?
    EnCase v7 search hits in compound files?
    How to search compound files
    iOS 8.3 JB ready
    Sunglasses
    现代福尔摩斯
  • 原文地址:https://www.cnblogs.com/whatisfantasy/p/6037060.html
Copyright © 2011-2022 走看看