Python系列之反射、面向对象

 

 

一、反射

说反射之前先介绍一下__import__方法,这个和import导入模块的另一种方式

1. import  commons
2. __import__('commons') 

如果是多层导入:

1. from list.text import commons 
2. __import__(' list.text.commons',fromlist=True) #如果不加上fromlist=True,只会导入list目录

反射即想到4个内置函数分别为:getattr、hasattr、setattr、delattr  获取成员、检查成员、设置成员、删除成员下面逐一介绍先看例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class  Foo( object ):
 
     def  __init__( self ):
         self .name  =  'abc'
 
     def  func( self ):
         return  'ok'
 
obj  =  Foo()
#获取成员
ret  =  getattr (obj,  'func' ) #获取的是个对象
=  ret()
print (r)
#检查成员
ret  =  hasattr (obj, 'func' ) #因为有func方法所以返回True
print (ret)
#设置成员
print (obj.name)  #设置之前为:abc
ret  =  setattr (obj, 'name' , 19 )
print (obj.name)  #设置之后为:19
#删除成员
print (obj.name)  #abc
delattr (obj, 'name' )
print (obj.name)  #报错

对于反射小节:

1.根据字符串的形式导入模块。
2.根据字符串的形式去对象(某个模块)中操作其成员 

实例:基于反射实现类Web框架的路由系统

实现思路:规定用户输入格式 模块名/函数名 通过__import__的形式导入模块并通过 hasattr和getattr 检查并获取函数返回值。

二、面向对象

面向对象简称OOP,面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。

语法格式见下图:

关键字class 和函数def 是一样的。类名通常是大写开头的单词,定义号类后就可以创建实例如上图的类加()就相当于创建一个类的实例obj

  1. def Bar(self)  其中self 为形式参数 
  2. 和实例化对象obj的内存地址相同

类的三大特性:封装、继承、多态

1、封装

面向对象编程的一个重要特点就是数据封装。例如:

复制代码
class Foo:
    def fetch(self):
        print(self.beckend)  #self 直接在对象里面取值

obj = Foo()
obj.beckend = 'www.baidu.com'  #把beckend封装在对象里面
obj.fetch()
复制代码
复制代码
class Foo :
        '''构造方法'''
    def __init__(self,bk):
        self.backend = bk  # 把obj对象的参数封装在 init 方法里
    def fetch(self):
        print(self.backend)
    def add(self):
        print(self.backend)
obj = Foo('www.xxx.com')
obj.fetch()
obj.add()
复制代码

通过代码我们看到__init__:称之为构造方法,需要注意__init__的第一个参数永远是self,表示的实例本身

封装的意义:当同一类型的方法具有相同的参数时,可以直接封装到对象里减少代码量。

使用场景把类当作模版,创建多个对象并且对象内封装的数据可以不同。

2、继承

当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class),有几点要注意:

  1. 继承要在子类加上父类的类名
  2. 子类和父类都有的方法,优先找子类的方法
  3. python里面可以继承多个类C#,java 不可以多继承
  4. 如果继承多个类,继承顺序为从左至右

 例如下面的例子:

复制代码
class Animals:
    def chi(self):
        print(self.Name + ' 吃')
    def he(self):
        print(self.Name + ' 喝')

class Dog(Animals):
    def __init__(self,name):
        self.Name = name
    def jiao(self):
        print(self.Name + ' 叫')
xxoo =Dog('某某某')

xxoo.chi()
xxoo.he()
xxoo.jiao()
复制代码
复制代码
class Animals:
    def chi(self):
        print(self.Name +' 吃')

    def he(self):
        print(self.Name + ' 喝')

class Uncle:
    def du(self):
        print(self.Name + ' 赌')

class Dog(Animals,Uncle):
    def __init__(self,name):
        self.Name = name

xxoo = Dog('某某某')
xxoo.chi()
xxoo.du()
复制代码

关于继承顺序需要注意例如 E继承(C,D) -->C继承(A)-->D继承(B) 如下图(python3):

复制代码
class A:
    def f1(self):
        print('A')
class B:
    def f(self):
        print('B')
class C(A):
    def f(self):
        print('C')
class D(B):
    def f1(self):
        print('D')

class E(C,D):
    def f(self):
        print('E')
aa = E()
aa.f1()
复制代码

第二种查找顺序:E继承(C,D)-->C继承(A),D继承(B)-->A和B都继承(Boos) ,查找顺序如下(python3):

复制代码
class Boos:
    def f1(self):
        print('Boos')

class A(Boos):
    def f(self):
        print('A')
class B(Boos):
    def f(self):
        print('B')
class C(A):
    def f(self):
        print('C')
class D(B):
    def f1(self):
        print('D')

class E(C,D):
    def f(self):
        print('E')

aa = E()
aa.f1()
复制代码

  下面说下python27的查找顺序是什么那?

未继承object为经典类查找顺序--> 深度优先

3、多态

即多种形态....

补充:

关于继承如何执行父类的构造方法那?有两种方法如下代码:

复制代码
class Annimal:
    def __init__(self):
        print('Annimal的构造方法')

        self.ty = '动物'

class Cat(Annimal):
    def __init__(self):
        print('Cat的构造方法')
        self.n = '猫'
        super(Cat, self).__init__()  #推荐用这种
        # Annimal.__init__(self)        #第二种方式
c = Cat()
复制代码

查找源码的过程(self.xxxx(),从底层开始找)

三、成员

分别有静态字段、静态方法、类方法、特性、普通字段、普通方法、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class  Provice:
     #静态字段
     country  = 'China'
     def  __init__( self ,name):
         #普通字段
         self .name  =  name
      #普通方法
     def  show( self ):
         print ( 'show' )
 
     @staticmethod   #静态方法
     def  xo(arg):
         print ( 'xo' )
         print (arg)
     @classmethod   #类方法,必须要有个cls参数:自动传入类名
     def  xxoo( cls ):
         print ( 'xxoo' , cls )
 
     def  start( self ):
         print ( 'start' )
     @property  #特性
     def  end( self ):
         print ( 'end' )
     @end .setter
     def  end( self ,values):
         print (values)
         self .name  =  values  #也可以更改内存里的值
 
Provice.country  #类访问静态字段
Provice.xo( 'alex' #类访问静态方法
Provice.xxoo()  #访问类方法
 
#获取特性值
obj  =  Provice( 'alex' )
obj.end
#设置特性值
obj1 =  Provice( 'alex' )
obj1.end = '123'
print (obj1.name)
 
#普通方法
obj1 =  Provice( 'alex' )
obj1.show()
 
#普通字段
obj1 =  Provice( 'alex' )
print (obj1.name)

成员小节:

  1. 自己去访问自己的成员,除了类中的方法
  2. 通过类访问的有:静态字段、静态方法、类方法

  3. 通过对象访问:普通字段、普通方法 、特性

复制代码
静态字段:存在类中 ,静态字段存在的意:把对象里面重复的数据只在类里保存一份
静态方法 :没有self 可以传参数,调用的时候也需要传入参数 ,存在的意义:不需要创建对象,就可以访问此方法 ,为类而生
类方法:必须要有个cls参数:自动传入类名
特性  对象调用 、不能加参数,执行不用加括号

普通字段,存放在对象中
普通方法  存在的意义:普通方法如果要想被调用就需要创建self ,为对象而生
复制代码

四、成员修饰符

 公有成员:任何地方都能访问
 私有成员:只有在类的内部才能访问,定义方式为命名时,前两个字符为下划线,如 "__test"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class  Person:
     country  =  'China'         #静态字段,属于公有成员
     __planet  =  'Earth'        #静态字段,属于私有成员
     def  __init__( self ,name):
         print ( 'Person build self.name' )
         self .name  =  name
          
     def  say( self ):
         print ( 'The planet is %s' % Person.__planet)     #在类的内部访问私有静态字段
          
p1  =  Person( 'Nothing' )
p1.say()
print (p1.country)             #访问公有静态字段
print (p1.__planet)           #访问私有静态字段
 
#执行结果:
Person build  self .name
The planet  is  Earth          #在类的内部可以访问
     print (p1.__planet)
China                    #外部可以访问公有静态字段
AttributeError:  'Person'  object  has no attribute  '__planet'     #外部无法访问私有静态字段

小节:私有成员只能在类内部使用,其他的都不能使用包括继承的子类,也不是绝对 也可以通过访问,但是不推荐

对象._类名__字段名

类的特殊成员:

1
2
3
4
5
6
7
8
9
10
__doc__       表示类的描述信息
__module__     表示当前操作的对象在那个模块
__class__      表示当前操作的对象的类是什么
__init__       构造方法,通过类创建对象时,自动触发执行
__call__       对象后面加括号,触发执行。
__dict__       类或对象中的所有成员
__str__       如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
__init__    构造方法,通过类创建对象时,自动触发执行
 
__setitem__,__getitem__,__delitem__ 用于索引操作,如字典。分别表示获取、设置、删除数据

五、异常处理  

异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。

一般情况下,在Python无法正常处理程序时就会发生一个异常。

异常是Python对象,表示一个错误。

当Python脚本发生异常时我们需要捕获处理它,否则程序会终止执行。

语法:

1
2
3
4
5
6
7
8
9
10
11
try :
<语句>         #运行别的代码
except  <名字>:
<语句>         #如果在try部份引发了'name'异常
except  <名字>,<数据>:
<语句>         #如果引发了'name'异常,获得附加的数据
else :
<语句>         #如果没有异常发生
 
finally :
         xxxx  

标准的异常有:

五、单例模式

  单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。

 用装饰器方式实现

复制代码
def wapper(cls):
    instances = {}
    def inner():
        if cls not in instances:
            instances[cls] = cls()
        return cls
    return inner

@wapper
def Foo():
    pass

f1 =Foo()
f2 =Foo()

print(f1 is f2)
复制代码

静态方法实现:

复制代码
class ConnectPool:
    __instatnce=None
    @staticmethod
    def get_instance():
        if ConnectPool.__instatnce:
            return ConnectPool.__instatnce
        else:
            ConnectPool.__instatnce = ConnectPool()
            return ConnectPool.__instatnce

obj =ConnectPool.get_instance()
print(obj)
obj1 =ConnectPool.get_instance()
print(obj1)
复制代码

  

一、反射

说反射之前先介绍一下__import__方法,这个和import导入模块的另一种方式

1. import  commons
2. __import__('commons') 

如果是多层导入:

1. from list.text import commons 
2. __import__(' list.text.commons',fromlist=True) #如果不加上fromlist=True,只会导入list目录

反射即想到4个内置函数分别为:getattr、hasattr、setattr、delattr  获取成员、检查成员、设置成员、删除成员下面逐一介绍先看例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class  Foo( object ):
 
     def  __init__( self ):
         self .name  =  'abc'
 
     def  func( self ):
         return  'ok'
 
obj  =  Foo()
#获取成员
ret  =  getattr (obj,  'func' ) #获取的是个对象
=  ret()
print (r)
#检查成员
ret  =  hasattr (obj, 'func' ) #因为有func方法所以返回True
print (ret)
#设置成员
print (obj.name)  #设置之前为:abc
ret  =  setattr (obj, 'name' , 19 )
print (obj.name)  #设置之后为:19
#删除成员
print (obj.name)  #abc
delattr (obj, 'name' )
print (obj.name)  #报错

对于反射小节:

1.根据字符串的形式导入模块。
2.根据字符串的形式去对象(某个模块)中操作其成员 

实例:基于反射实现类Web框架的路由系统

实现思路:规定用户输入格式 模块名/函数名 通过__import__的形式导入模块并通过 hasattr和getattr 检查并获取函数返回值。

二、面向对象

面向对象简称OOP,面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。

语法格式见下图:

关键字class 和函数def 是一样的。类名通常是大写开头的单词,定义号类后就可以创建实例如上图的类加()就相当于创建一个类的实例obj

  1. def Bar(self)  其中self 为形式参数 
  2. 和实例化对象obj的内存地址相同

类的三大特性:封装、继承、多态

1、封装

面向对象编程的一个重要特点就是数据封装。例如:

复制代码
class Foo:
    def fetch(self):
        print(self.beckend)  #self 直接在对象里面取值

obj = Foo()
obj.beckend = 'www.baidu.com'  #把beckend封装在对象里面
obj.fetch()
复制代码
复制代码
class Foo :
        '''构造方法'''
    def __init__(self,bk):
        self.backend = bk  # 把obj对象的参数封装在 init 方法里
    def fetch(self):
        print(self.backend)
    def add(self):
        print(self.backend)
obj = Foo('www.xxx.com')
obj.fetch()
obj.add()
复制代码

通过代码我们看到__init__:称之为构造方法,需要注意__init__的第一个参数永远是self,表示的实例本身

封装的意义:当同一类型的方法具有相同的参数时,可以直接封装到对象里减少代码量。

使用场景把类当作模版,创建多个对象并且对象内封装的数据可以不同。

2、继承

当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class),有几点要注意:

  1. 继承要在子类加上父类的类名
  2. 子类和父类都有的方法,优先找子类的方法
  3. python里面可以继承多个类C#,java 不可以多继承
  4. 如果继承多个类,继承顺序为从左至右

 例如下面的例子:

复制代码
class Animals:
    def chi(self):
        print(self.Name + ' 吃')
    def he(self):
        print(self.Name + ' 喝')

class Dog(Animals):
    def __init__(self,name):
        self.Name = name
    def jiao(self):
        print(self.Name + ' 叫')
xxoo =Dog('某某某')

xxoo.chi()
xxoo.he()
xxoo.jiao()
复制代码
复制代码
class Animals:
    def chi(self):
        print(self.Name +' 吃')

    def he(self):
        print(self.Name + ' 喝')

class Uncle:
    def du(self):
        print(self.Name + ' 赌')

class Dog(Animals,Uncle):
    def __init__(self,name):
        self.Name = name

xxoo = Dog('某某某')
xxoo.chi()
xxoo.du()
复制代码

关于继承顺序需要注意例如 E继承(C,D) -->C继承(A)-->D继承(B) 如下图(python3):

复制代码
class A:
    def f1(self):
        print('A')
class B:
    def f(self):
        print('B')
class C(A):
    def f(self):
        print('C')
class D(B):
    def f1(self):
        print('D')

class E(C,D):
    def f(self):
        print('E')
aa = E()
aa.f1()
复制代码

第二种查找顺序:E继承(C,D)-->C继承(A),D继承(B)-->A和B都继承(Boos) ,查找顺序如下(python3):

复制代码
class Boos:
    def f1(self):
        print('Boos')

class A(Boos):
    def f(self):
        print('A')
class B(Boos):
    def f(self):
        print('B')
class C(A):
    def f(self):
        print('C')
class D(B):
    def f1(self):
        print('D')

class E(C,D):
    def f(self):
        print('E')

aa = E()
aa.f1()
复制代码

  下面说下python27的查找顺序是什么那?

未继承object为经典类查找顺序--> 深度优先

3、多态

即多种形态....

补充:

关于继承如何执行父类的构造方法那?有两种方法如下代码:

复制代码
class Annimal:
    def __init__(self):
        print('Annimal的构造方法')

        self.ty = '动物'

class Cat(Annimal):
    def __init__(self):
        print('Cat的构造方法')
        self.n = '猫'
        super(Cat, self).__init__()  #推荐用这种
        # Annimal.__init__(self)        #第二种方式
c = Cat()
复制代码

查找源码的过程(self.xxxx(),从底层开始找)

三、成员

分别有静态字段、静态方法、类方法、特性、普通字段、普通方法、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class  Provice:
     #静态字段
     country  = 'China'
     def  __init__( self ,name):
         #普通字段
         self .name  =  name
      #普通方法
     def  show( self ):
         print ( 'show' )
 
     @staticmethod   #静态方法
     def  xo(arg):
         print ( 'xo' )
         print (arg)
     @classmethod   #类方法,必须要有个cls参数:自动传入类名
     def  xxoo( cls ):
         print ( 'xxoo' , cls )
 
     def  start( self ):
         print ( 'start' )
     @property  #特性
     def  end( self ):
         print ( 'end' )
     @end .setter
     def  end( self ,values):
         print (values)
         self .name  =  values  #也可以更改内存里的值
 
Provice.country  #类访问静态字段
Provice.xo( 'alex' #类访问静态方法
Provice.xxoo()  #访问类方法
 
#获取特性值
obj  =  Provice( 'alex' )
obj.end
#设置特性值
obj1 =  Provice( 'alex' )
obj1.end = '123'
print (obj1.name)
 
#普通方法
obj1 =  Provice( 'alex' )
obj1.show()
 
#普通字段
obj1 =  Provice( 'alex' )
print (obj1.name)

成员小节:

  1. 自己去访问自己的成员,除了类中的方法
  2. 通过类访问的有:静态字段、静态方法、类方法

  3. 通过对象访问:普通字段、普通方法 、特性

复制代码
静态字段:存在类中 ,静态字段存在的意:把对象里面重复的数据只在类里保存一份
静态方法 :没有self 可以传参数,调用的时候也需要传入参数 ,存在的意义:不需要创建对象,就可以访问此方法 ,为类而生
类方法:必须要有个cls参数:自动传入类名
特性  对象调用 、不能加参数,执行不用加括号

普通字段,存放在对象中
普通方法  存在的意义:普通方法如果要想被调用就需要创建self ,为对象而生
复制代码

四、成员修饰符

 公有成员:任何地方都能访问
 私有成员:只有在类的内部才能访问,定义方式为命名时,前两个字符为下划线,如 "__test"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class  Person:
     country  =  'China'         #静态字段,属于公有成员
     __planet  =  'Earth'        #静态字段,属于私有成员
     def  __init__( self ,name):
         print ( 'Person build self.name' )
         self .name  =  name
          
     def  say( self ):
         print ( 'The planet is %s' % Person.__planet)     #在类的内部访问私有静态字段
          
p1  =  Person( 'Nothing' )
p1.say()
print (p1.country)             #访问公有静态字段
print (p1.__planet)           #访问私有静态字段
 
#执行结果:
Person build  self .name
The planet  is  Earth          #在类的内部可以访问
     print (p1.__planet)
China                    #外部可以访问公有静态字段
AttributeError:  'Person'  object  has no attribute  '__planet'     #外部无法访问私有静态字段

小节:私有成员只能在类内部使用,其他的都不能使用包括继承的子类,也不是绝对 也可以通过访问,但是不推荐

对象._类名__字段名

类的特殊成员:

1
2
3
4
5
6
7
8
9
10
__doc__       表示类的描述信息
__module__     表示当前操作的对象在那个模块
__class__      表示当前操作的对象的类是什么
__init__       构造方法,通过类创建对象时,自动触发执行
__call__       对象后面加括号,触发执行。
__dict__       类或对象中的所有成员
__str__       如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
__init__    构造方法,通过类创建对象时,自动触发执行
 
__setitem__,__getitem__,__delitem__ 用于索引操作,如字典。分别表示获取、设置、删除数据

五、异常处理  

异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。

一般情况下,在Python无法正常处理程序时就会发生一个异常。

异常是Python对象,表示一个错误。

当Python脚本发生异常时我们需要捕获处理它,否则程序会终止执行。

语法:

1
2
3
4
5
6
7
8
9
10
11
try :
<语句>         #运行别的代码
except  <名字>:
<语句>         #如果在try部份引发了'name'异常
except  <名字>,<数据>:
<语句>         #如果引发了'name'异常,获得附加的数据
else :
<语句>         #如果没有异常发生
 
finally :
         xxxx  

标准的异常有:

五、单例模式

  单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。

 用装饰器方式实现

复制代码
def wapper(cls):
    instances = {}
    def inner():
        if cls not in instances:
            instances[cls] = cls()
        return cls
    return inner

@wapper
def Foo():
    pass

f1 =Foo()
f2 =Foo()

print(f1 is f2)
复制代码

静态方法实现:

复制代码
class ConnectPool:
    __instatnce=None
    @staticmethod
    def get_instance():
        if ConnectPool.__instatnce:
            return ConnectPool.__instatnce
        else:
            ConnectPool.__instatnce = ConnectPool()
            return ConnectPool.__instatnce

obj =ConnectPool.get_instance()
print(obj)
obj1 =ConnectPool.get_instance()
print(obj1)
复制代码

  

猜你喜欢

转载自www.cnblogs.com/lazily/p/9092561.html