Python:反射和面向对象(一)

  • 反射

在所有语言里面都有这个名词:反射。反射也就是:通过字符串的形式,导入模块。通过字符串的形式,去模块中寻找指定函数,并执行。Python中的反射功能是由以下四个内置函数提供:

hasattr(模块,"成员"):根据字符串的形式去某个模块中检查是否含有某成员

getattr(模块,"成员"):根据字符串的形式去某个模块中获取成员

setattr(模块,"成员"):根据字符串的形式去某个模块中设置成员

delattr(模块,"成员"):根据字符串的形式去某个模块中删除成员

 

正常导入模块:

首先定义一个模块,模块里面有几个函数:

然后导入模块,执行函数:

import commons
r = commons.f1()
print(r)

#打印结果:
f1
F1

 此时有个需求:根据用户输入的内容,导入模块

#用户输入什么我们就拿到哪个字符串
inp = input("请输入模块:")
print(inp,type(inp))

#打印结果:
请输入模块:commons
commons <class 'str'>

 

 再根据用户输入的内容,导入模块,执行函数:

 之前我们学过__import__(字符串):用于以字符串的形式去某个模块中找函数,so:

#import commons as CC
#本质:__import__
#DD = __import__("commons")

#应用通过字符串形式导入模块:

inp = input("请输入模块:")
print(inp,type(inp))

r = __import__(inp)
#模块中寻找函数并且执行函数
#此时f1()还并不是字符串
ret = r.f1()
print(ret)

#打印结果:
请输入模块:commons
commons <class 'str'>
f1
F1

 

 

 现在根据字符串形式去模块中寻找函数并且执行函数:

inp_name = input("请输入模块:")
inp_func = input("请输入要执行的函数:")
#导入输入的模块
inp = __import__(inp_name)
#获取模块中的函数名
target_func = getattr(inp,inp_func)
#执行函数
ret = target_func()
print(ret)
#打印结果:
请输入模块:commons
请输入要执行的函数f1
f1
F1

 

# 查看是否存在,不存在False,存在True
r = hasattr(commons,"NAME")
print(r)

# 设置成员
r = setattr(commons,"ARG",lambda a: a + 1)
print(r)

# 删除成员
delattr(commons,"NAME")
#查看已删除成员是否还存在
r = hasattr(commons,"NAME")
print(r)

 

注:

#设置None:如果找到成员f1,就会执行;如果没有找到,就会报错
target_func = getattr(commons,"Name",None)
ret = target_func()
print(ret)

 

扩展两种导入模块的方式:

a = __import__("模块名")

a = __import__("文件名.文件名.模块名",fromlist=True)

 示例:

from lib import account

url = input("请输入url:")
if url.endswith("login"):
    r = account.login()
    print(r)
elif url.endswith("logout"):
    r = account.logout()
    print(r)
elif url.endswith("nb"):
    r = account.nb()
    print(r)
else:
    print("404")
View Code
from lib import account

url= input("请输入url")
inp = url.split("/")[-1]
if hasattr(account,inp):
    target_func = getattr(account,inp)
    r = target_func()
    print(r)
else:
    print("404")
View Code
#模块名/函数名
url = input("请输入url:")
#模块名和函数名的格式
target_module,target_func = url.split("/")
#导入用户输入的模块
m = __import__("lib."+target_module,fromlist=True)
if hasattr(m,target_func):
    target_func = getattr(m,target_func)
    r = target_func()
    print(r)
else:
    print("404")
View Code

 

总结:反射是通过字符串的形式去对象(某个模块)中操作其成员。一切事物皆对象!

 

 

 

  • 面向对象基础

 概述:

C#、Java只能用面向对象编程。Ruby、Python是可以用函数编程和面向对象。

  • 面向过程编程:根据业务逻辑从上到下写代码
  • 函数式编程:讲某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
  • 面向对象编程:对函数进行分类和封装

面向过程编程:初学者最容易接受

while True:
    if cpu利用率 > 90%:
        #发送邮件提醒
        连接邮箱服务器
        发送邮件
        关闭连接
 
    if 硬盘使用空间 > 90%:
        #发送邮件提醒
        连接邮箱服务器
        发送邮件
        关闭连接
 
    if 内存占用 > 80%:
        #发送邮件提醒
        连接邮箱服务器
        发送邮件
        关闭连接
面向过程编程

函数式编程:增强代码的重用性和可读性

def 发送邮件(内容)
    #发送邮件提醒
    连接邮箱服务器
    发送邮件
    关闭连接
 
while True:
 
    if cpu利用率 > 90%:
        发送邮件('CPU报警')
 
    if 硬盘使用空间 > 90%:
        发送邮件('硬盘报警')
 
    if 内存占用 > 80%:
        发送邮件('内存报警') 
函数式编程

 

面向对象编程:是一种编程方式,需要使用“类”和“对象”来实现,所以,面向对象编程其实就是对“类”和“对象”的使用。

面向对象不是所有情况都适用

  类就是一个模板,模板里可以包含多个函数,函数里实现一些功能

  对象则是根据模板创建的实例,通过实例对象可以执行类中的函数

注:

  •  class是关键字,表示类
  • 创建对象,在类名称后加括号即可
  • 类中定义的函数叫做“方法”
class Foo:
    def Bar(self):
        print("Bar")
    def Hello(self):
        print("Hello")

obj = Foo()
obj.Bar()
obj.Hello()

函数式编程:执行函数

面向对象编程:创建对象  通过对象执行方法

 

 

面向对象三大特性

面向对象的三大特性:封装、继承、多态

  • 封装

封装,将内容封装到某个地方,以后再去调用被封装在某处的内容。所有在使用面向对象的封装特性时,需要:

使用场景:

1、当同一类型的方法具有相同参数时,直接封装到对象即可。

2、把类当做模板,创建多个对象(对象内封装的数据可以不一样)

第一步:将内容封装到某处

__init__:构造方法

class Foo:
#####称为构造方法,根据类创建对象时自动执行
    def __init__(self,name):
        self.country = "中国"
        self.Name = name
    def eat(self):
        print(self.Name + "eat")
    def sleep(self):
        print(self.Name + "sleep")

#根据类Foo创建对象(或创建一个Foo类的实例)
#自动执行Foo类的__init__方法
obj1 = Foo("zou")
#根据类Foo创建对象(或创建一个Foo类的实例)
#自动执行Foo类的__init__方法
obj2 = Foo("zhang")

obj1.eat()
obj2.sleep()
#打印结果:
zoueat
zhangsleep

self是一个形式参数,当执行 obj1 = Foo("zou")时,self等于 obj1

              当执行 obj2 = Foo("zhang")时,self等于 obj2

 所以,内容其实被封装到了对象 obj1 和 obj2 中,每个对象中都有name属性。

 

第二步:从某处调用被封装的内容

  调用被封装的内容时,有两种情况:

1、通过对象直接调用被封装的内容

class Foo:
    def __init__(self,name,age):
        self.country = "中国"
        self.Name = name
        self.Age = age
    def eat(self):
        print(self.Name + "eat")
    def sleep(self):
        print(self.Name + "sleep")

#根据类Foo创建对象
#自动执行Foo类的__init__方法
obj1 = Foo("zou",18)

#直接调用obj1对象的属性
print(obj1.Name)
print(obj1.Age)

#根据类Foo创建对象
#自动执行Foo类的__init__方法
obj2 = Foo("zhang",19)

#直接调用obj2对象的属性
print(obj2.Name)
print(obj2.Age)
#打印结果:
zou
18
zhang
19

2、通过self间接调用被封装的内容

class Foo:
    def __init__(self,name,age):
        self.Name = name
        self.Age = age

    def f(self):
        print(self.Name)
        print(self.Age)

obj1 = Foo("zou",18)
obj1.f() # Python默认会将obj1传给self参数,即:obj1.f(obj1),所以,此时方法内部的 self = obj1,即:self.name 是 zou ;self.age 是 18

obj2 = Foo("zhang",19)
obj2.f() # Python默认会将obj2传给self参数,即:obj2.f(obj2),所以,此时方法内部的 self = obj2,即:self.name 是 zhang ;self.age 是 19

 

 总结:对于面向对象的封装来说,其实就是使用构造方法将内容封装到对象中,然后通过对象直接或者self间接获取被封装的内容。

练习:在终端输出如下信息 

小明,10岁,男,上山去砍柴

小明,10岁,男,开车去东北

老李,90岁,男,上山去砍柴

老李,90岁,男,开车去东北 

def kanchai(name, age, gender):
    print "%s,%s岁,%s,上山去砍柴" %(name, age, gender)


def qudongbei(name, age, gender):
    print "%s,%s岁,%s,开车去东北" %(name, age, gender)


kanchai('小明', 10, '')
qudongbei('小明', 10, '')


kanchai('老李', 90, '')
qudongbei('老李', 90, '')
函数式编程
class Foo:
    
    def __init__(self, name, age ,gender):
        self.name = name
        self.age = age
        self.gender = gender

    def kanchai(self):
        print "%s,%s岁,%s,上山去砍柴" %(self.name, self.age, self.gender)

    def qudongbei(self):
        print "%s,%s岁,%s,开车去东北" %(self.name, self.age, self.gender)


xiaoming = Foo('小明', 10, '')
xiaoming.kanchai()
xiaoming.qudongbei()

laoli = Foo('老李', 90, '')
laoli.kanchai()
laoli.qudongbei()
面向对象编程

上述对比可以看出,如果使用函数式编程,需要在每次执行函数时传入相同的参数,如果参数多的话,又需要粘贴复制了... 而对于面向对象只需要在创建对象时,将所有需要的参数封装到当前对象中,之后再次使用时,通过self间接去当前对象中取值即可。

 

  • 继承

 继承:面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容。

例如:

动物共同功能:吃、喝、睡

猫特有功能:喵喵叫

狗特有功能:汪汪叫

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 + "")

class Cat(Animals):
    def __init__(self,name):
        self.Name = name
    def jiao(self):
        print(self.Name + "")

obj1 = Dog("小黑")
obj1.chi()
obj1.jiao()
obj2 = Cat("小花")
obj2.chi()
obj2.jiao()
#打印结果:
小黑吃
小黑汪
小花吃
小花喵

所以,对于面向对象的继承来说,就是将多个类共有的方法提取到父类(基类)中,子类(派生类)仅需继承父类(基类)而不必一一实现每个方法。

 

注:

派生类可以继承基类中所有的功能

派生类和基类某一方法同时存在,优先找派生类

class Animals:
    def chi(self):
        print(self.Name + "")
    def he(self):
        print(self.Name + "")
    def sleep(self):
        print(self.Name + "")
class Uncle:
    def play(self):
        print(self.Name + "")
    def sleep(self):
        print("sleep")
class Dog(Animals,Uncle):
    def __init__(self,name):
        self.Name = name
    def talk(self):
        print(self.Name + "说话")

obj = Dog("小黑")
obj.chi()
obj.sleep()
#打印结果:
小黑吃
小黑睡


#####################


class Animals: def chi(self): print(self.Name + "") def he(self): print(self.Name + "") def sleeping(self): print(self.Name + "") class Uncle: def play(self): print(self.Name + "") def sleep(self): print("sleep") class Dog(Animals,Uncle): def __init__(self,name): self.Name = name def talk(self): print(self.Name + "说话") obj = Dog("小黑") obj.chi() obj.sleep() #打印结果: 小黑吃 sleep ########## 查找顺序:Dog-->Animals-->Uncle

Python的类可以继承多个类,Java和C#中则只能继承一个类

Python的类如果继承了多个类,那么寻找方法的方式有两种(Python3中)

第一种:

class A:
    def f1(self):
        print("A")


class B:
    def f1(self):
        print("B")


class C(A):
    def f1(self):
        print("C")


class D(B):
    def f1(self):
        print("D")


class E(C, D):
    def f1(self):
        print("E")


obj = E()
obj.f()
#查找顺序:E-->C-->A-->D-->B

顺序见图:

第二种:

class All():
    def f(self):
        print("All")


class A(All):
    def f1(self):
        print("A")


class B(All):
    def f1(self):
        print("B")


class C(A):
    def f1(self):
        print("C")


class D(B):
    def f1(self):
        print("D")


class E(C, D):
    def f1(self):
        print("E")


obj = E()
obj.f()

# 查找顺序:E-C-A-D-B-All

顺序见图:

 

  • 多态

 Python不支持多态并且也用不到多态,多态的概念是应用于C#和Java这一类强类型语言中,而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) 

 

posted @ 2016-06-01 08:58  阿肉  阅读(324)  评论(0编辑  收藏  举报