美文网首页
python08-反射 & 面向对象(一)

python08-反射 & 面向对象(一)

作者: AndroidCat | 来源:发表于2017-05-10 09:17 被阅读0次

    反射

    • 反射:
      1. 通过字符串的形式导入模块
      2. 通过字符串的形式去模块中寻找制定的成员(属性、函数),并使用
    # 1.创建index.py主程序
    # 2.创建commoms模块提供函数
    # 3.引入commons模块调用模块中的函数
    
    # commoms.py
    def f1():
        print('F1')
        return 'F1'
    
    # index.py
    import commons
    if __name__ == '__main__':
        ret = commons.f1()
        print(ret) # F1
    
    • 上面的函数是正常导入并执行,如果想导入用户输入的模块名,并调用用户输入的函数,则:
    # index.py
    if __name__ == '__main__':
        module = input('请输入模块名:')
        mod = __import__(module)
        # ret = mod.f1() # 正常调用
        # print(ret) # 正常输出
        attr = input('请输入方法名:')
        meth = getattr(mod,attr)
        ret = meth()
        print(ret)
    
    • 上面的函数相当于调用了2个函数

      • __import__():通过字符串导入模块对象
      • getattr(module,attr):获取模块里的元素
    • 其实getattr()函数才叫反射,通过字符串的形式在模块中寻找相应的元素,如果元素不存在,则报错.

    • 可以通过给getattr(module,arrtib,def)设置默认值,防止报错

    • 反射函数

      • getattr():获取属性
      • delattr():删除属性
      • hasattr():判断实行是否存在
      • setattr():添加或修改属性
    • python中,一切皆对象,通过反射,根据字符串去对象中(模块,类)获取元素

    • 扩展

      • 通过__import__()导入的模块如果存在的路径为:lib\modules\moudle.py
      • 如果导入的方式为:__import__('lib.modules.moudle'),则导入的为lib文件夹
      • 如果想解决这个问题,导入的方式为:__import__('lib.modules.moudle', fromlist=True)

    基于反射模拟web框架路由系统

    • 根据用户发送不同的url,服务器执行不同的操作,返回不同的结果
    • 原始操作:
      1. 截取url最后的字段,如login,logout,pay等
      2. 通过if,elif,else判断字段,然后执行模块里面的方法
    • 优化:
      1. 如果网站很大,有成百上千个方法,都要if,elif,else来判断,则需要写大量的判断代码
      2. 通过反射来获取相应的方法,然后调用,则可以不用修改index.py方法,只需要在模块里面添加响应的方法,让url中的字段去匹配
    • 完善:
      1. 但是如果网站太大了,所有的方法都写在一个模块里面,维护起来会很麻烦,同时反射获取方法需要更长的时间
      2. 通过分模块来管理不同功能的方法,在url中把模块和方法名都加上,切割后通过__import__(path, fromlist = True)来导入模块,通过反射获取方法
    # 1.创建主程序index.py
    # 2.创建功能模块
    # 3.截取url,获取里面的地址参数执行不同的方法
    
    # url = input("请输入url:")
    url = 'www.yuhhcompany.com/account/login'
    regex = 'www.yuhhcompany.com'
    ret = re.match(regex, url)
    if ret != None:
        # 匹配成功
        host, module, method = url.split('/')
        mod = __import__(module, fromlist=True)
        if hasattr(mod, method):
            ret = getattr(mod, method)()
    
    • 所有的web框架:php,c#,java,Django本质都是这个道理

    面向对象

    • 编程语言:

      • java、c#只能通过面向对象编程
      • Python可以通过函数式编程,也可以通过面向对象编程
    • Python面向对象:

      • class:创建类关键字
      • 定义的函数,在函数式编程时称函数,面向对象编程称为方法
      • 方法参数self:每个方法都需要加上self参数,值为调用该方法的对象,点用方法时python会自动传入该参数,不需要自己传
      class Cat:
          def fun1(self):
              pass
          def fun2(self):
              pass
      
      cat1 = Cat()
      cat1.fun1()
      cat1.fun2()
      
    • 方法的参数self:

      • self代表调用方法的对象,不需要自己传入,当调用方法时,python自动帮我们传入该self参数
      class Cat:
          def fun1(self):
              print(self)
      cat1 = Cat()
      print(cat1) # <__main__.Cat object at 0x10073fc50>
      cat1.fun1() # <__main__.Cat object at 0x10073fc50>
      
      • 封装:

        • 如果一个类中多个方法需要用到同一个参数,每次都穿的话,太麻烦
        class Cat:
            def fun1(self, name, age):
                print(name, age)
            def fun2(self, name, age):
                print(name, age)
            def fun3(self, name, age):
                print(name, age)
        
        cat1 = Cat()
        cat1.fun1('yhh', 23)
        cat1.fun2('yhh', 23)
        cat1.fun3('yhh', 23)
        
        • 可以将重复的变量作为对象的属性:
          • 把参数赋值给对象,在方法中调用--封装
        class Cat:
            def fun1(self):
                print(self.name, self.age)
            def fun2(self):
                print(self.name, self.age)
            def fun3(self):
                print(self.name, self.age)
        
        cat1 = Cat()
        cat1.name = 'yhh'
        cat1.age = 23
        cat1.fun1()
        cat1.fun2()
        cat1.fun3()
        
        • 封装使用场景:

          • 连接操作数据库,对数据库的操作(curd)都需要用到ip,port,user,password,content等,如果每个方法都传ip,port,user,passowrd,这样方法的参数重复且调用的时候很麻烦,如果把它们都封装到对象里,直接在对象里调用,这样重复的参数只需要穿一遍即可.
        • 封装步骤

          • 上面的封装过程不够好,因为如果别人看你的代码,别人不一定知道调用方法前需要封装数据,可以优化为:
          • 创建对象时会调用构造方法__init__(),对象销毁的时候会调用__del__()方法(析构方法)
        class Cat:
            def __init__(self, name, age):
                self.name = name
                self.age = age
            def fun1(self):
                print(self.name, self.age)
            def fun2(self):
                print(self.name, self.age)
            def fun3(self):
                print(self.name, self.age)
        
      • 对象序列化

        • 在python中,对象可以通过pickle序列化,然后在本地持久化,可以用来存档
        • 不能用json,因为json只能转成python的基本类型,自定义类不属于基本类型
        import pickle
        
        # 存档
        with open('object.pickle', mode='wb') as file:
            pickle.dump(cat1,file)
        
        # 读档
        with open('object.pickle', mode='rb') as file:
            cat1 = pickle.load(file)
            cat1.fun1() # YHH 23
        
      • 继承

        • python中继承是需要在子类的类名后跟上:(父类类名)
        • 父类--子类
        • 基类--派生类
        • 派生类和父类有相同的方法时,以派生类为主
        class Father:
            def fun1(self):
                print('Father')
        
        class Son(Father):
            def fun2(self):
                print('Son')
        
        son = Son()
        son.fun1()  # Father
        son.fun2()  # Son
        
      • 多继承

        • java、c#只支持单继承
        • python可以多继承
        • 如果A继承B和C,B和C都有相同的方法,则以继承时写在左边的为主,如果A也有这个方法,则以A为主
      • 多继承面试题:

      在pytho3.5中:
      # 如果继承关系
      class E(C,D):
          pass
      # A --> C --> E
      # B --> D --> E
      # E继承CD,C继承A,D即成B
      # 则调用的顺序为:E --> C --> A --> D --> B(顶层没有同一个基类)
      
      # 如果A和B同时又继承BASE基类,则调用顺序为:
      E --> C --> A --> D --> B --> BASE(顶层有同一个基类)
      python2.7不一样
      
      • 多态

        • python本身语言特性就支持多态,像java,c#等因为是强类型语言,比较复杂
        lass Cat():
            def fun1(self):
                print('fun1')
        
        class Dog():
            def fun1(self):
                print('fun1')
        
        def function(animal):
            animal.fun1()
        
        function(Cat())
        function(Dog())
        
        • 其他语言有重载,python不支持
      • 接口

        • python语言没有接口一说
        • 接口类型:
          • 代码级别:interface
          • 业务级别:访问后台的地址

    相关文章

      网友评论

          本文标题:python08-反射 & 面向对象(一)

          本文链接:https://www.haomeiwen.com/subject/nfpwtxtx.html