19 python快速上手

面向对象高级和应用

    • 1. 继承【补充】
      • 1.1 mro和c3算法
      • 1.2 py2和py3区别(了解)
    • 2. 内置函数补充
    • 3.异常处理
      • 3.1 异常细分
      • 3.2 自定义异常&抛出异常
      • 3.4 特殊的finally
    • 4.反射
      • 4.1 一些皆对象
      • 4.2 import_module + 反射
    • 总结

各位小伙伴想要博客相关资料的话关注公众号:chuanyeTry即可领取相关资料!

在这里插入图片描述

课程目标:掌握面向对象高级知识和相关应用。

今日概要

  • 继承【补充】
  • 内置函数【补充】
  • 异常处理
  • 反射

1. 继承【补充】

对于Python面向对象中的继承,我们已学过:

  • 继承存在意义:将公共的方法提取到父类中,有利于增加代码重用性。

  • 继承的编写方式:

    # 继承
    class Base(object):
        pass
    
    class Foo(Base):
        pass
    
    # 多继承
    class Base(object):
        pass
    
    class Bar(object):
        pass
    
    class Foo(Base,Bar):
        pass
    
  • 调用类中的成员时,遵循:

    • 优先在自己所在类中找,没有的话则去父类中找。
    • 如果类存在多继承(多个父类),则先找左边再找右边。

上述的知识点掌握之后,其实就可以解决继承相关的大部分问题。

但如果遇到一些特殊情况(不常见),你就可能不知道怎么搞了,例如:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.1 mro和c3算法

如果类中存在继承关系,在可以通过mro()获取当前类的继承关系(找成员的顺序)。

示例1:

在这里插入图片描述

mro(A) = [A] + [B,C]
mro(A) = [A,B,C]
mro(A) = [A] + merge( mro(B), mro(C), [B,C] )
mro(A) = [A] + merge( [object], [object], [] )
mro(A) = [A] + [B,C,object]
mro(A) = [A,B,C,object]
mro(A) = [A] + merge( mro(B), mro(C), [B,C] )
mro(A) = [A] + merge( [], [C], [,C] 
mro(A) = [A] + [B,C]
class C(object):
    pass

class B(object):
    pass

class A(B, C):
    pass

print( A.mro() )   # [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>]
print( A.__mro__ ) # (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>)

示例2:

在这里插入图片描述

mro(A) = [A] + merge( mro(B), mro(C), [B,C] )
mro(A) = [A] + merge( [], [D], [] )
mro(A) = [A] + [B,C,D]
mro(A) = [A,B,C,D]
class D(object):
    pass


class C(D):
    pass


class B(object):
    pass


class A(B, C):
    pass


print( A.mro() ) # [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>]

示例3:
在这里插入图片描述

mro(A) = [A] + merge( mro(B),mro(C),[B,C])
mro(A) = [A] + merge( [], [C], [C])
mro(A) = [A,B,D,C]
class D(object):
    pass


class C(object):
    pass


class B(D):
    pass


class A(B, C):
    pass


print(A.mro()) # [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.C'>, <class 'object'>]

示例4:

在这里插入图片描述

mro(A) = [A] + merge( mro(B), mro(C), [B,C])

mro(A) = [A] + merge( [B,D], [C,D], [B,C])

mro(A) = [A] + [B,C,D] 
mro(A) = [A,B,C,D] 
class D(object):
    pass


class C(D):
    pass


class B(D):
    pass


class A(B, C):
    pass


print(A.mro()) # [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>]

示例5:
在这里插入图片描述

简写为:A -> B -> D -> G -> H -> K -> C -> E -> F -> M -> N -> P -> object
mro(A) = [A] + merge( mro(B),          mro(C),      mro(P),      [B,C,P])
                  []   [N]     [P]          [P]

mro(A) = [A,B,D,G,H,K,C,E,F,M,N,P]

-----------------------------------------------------
mro(B) = [B] + merge( mro(D), mro(E), [D,E])

mro(D) = [D] + merge(mro(G),mro(H), [G,H])

mro(G) = [G]

mro(H) = [H,K]

mro(B) = [B] + merge( [], [E,M], [E])
mro(B) = [B,D,G,H,K,E,M]


-----------------------------------------------------
mro(C) = [C] + merge(mro(E),mro(F),[E,F])

mro(E) = [E,M]

mro(F) = [F,M,N] 

mro(C) = [C] + merge([M],[M,N] ,[])
mro(C) = [C,E,F,M,N]
class M:
    pass


class N:
    pass


class E(M):
    pass


class G:
    pass


class K:
    pass


class H(K):
    pass


class D(G, H):
    pass


class F(M, N):
    pass


class P:
    pass


class C(E, F):
    pass


class B(D, E):
    pass


class A(B, C, P):
    pass


print(A.mro()) # 简写为:A -> B -> D -> G -> H -> K -> C -> E -> F -> M -> N -> P -> object

特别补充:一句话搞定继承关系

不知道你是否发现,如果用正经的C3算法规则去分析一个类继承关系有点繁琐,尤其是遇到一个复杂的类也要分析很久。

所以,我自己根据经验总结了一句话赠送给大家:从左到右,深度优先,大小钻石,留住顶端,基于这句话可以更快的找到继承关系。

在这里插入图片描述

简写为:A -> B -> D -> G -> H -> K -> C -> E -> F -> M -> N -> P -> object

1.2 py2和py3区别(了解)

概述:

  • 在python2.2之前,只支持经典类【从左到右,深度优先,大小钻石,不留顶端】

  • 后来,Python想让类默认继承object(其他语言的面向对象基本上也都是默认都继承object),此时发现原来的经典类不能直接集成集成这个功能,有Bug。

  • 所以,Python决定不再原来的经典类上进行修改了,而是再创建一个新式类来支持这个功能。【从左到右,深度优先,大小钻石,留住顶端。】

    • 经典类,不继承object类型

      class Foo:
          pass
      
    • 新式类,直接或间接继承object

      class Base(object):
          pass
      
      class Foo(Base):
          pass
      
  • 这样,python2.2之后 中就出现了经典类和新式类共存。(正式支持是2.3)

  • 最终,python3中丢弃经典类,只保留新式类。

详细文档:
	https://www.python.org/dev/peps/pep-0253/#mro-method-resolution-order-the-lookup-rule
	https://www.python.org/download/releases/2.3/mro/

In classic Python, the rule is given by the following recursive function, also known as the left-to-right depth-first rule.

def classic_lookup(cls, name):
    if cls.__dict__.has_key(name):
        return cls.__dict__[name]
    for base in cls.__bases__:
        try:
            return classic_lookup(base, name)
        except AttributeError:
            pass
    raise AttributeError, name
    
The problem with this becomes apparent when we consider a "diamond diagram":

      class A:
        ^ ^  def save(self): ...
       /   \
      /     \
     /       \
    /         \
class B     class C:
    ^         ^  def save(self): ...
     \       /
      \     /
       \   /
        \ /
      class D
      

Arrows point from a subtype to its base type(s). This particular diagram means B and C derive from A, and D derives from B and C (and hence also, indirectly, from A).

Assume that C overrides the method save(), which is defined in the base A. (C.save() probably calls A.save() and then saves some of its own state.) B and D don't override save(). When we invoke save() on a D instance, which method is called? According to the classic lookup rule, A.save() is called, ignoring C.save()!

This is not good. It probably breaks C (its state doesn't get saved), defeating the whole purpose of inheriting from C in the first place.

Why was this not a problem in classic Python? Diamond diagrams are rarely found in classic Python class hierarchies. Most class hierarchies use single inheritance, and multiple inheritance is usually confined to mix-in classes. In fact, the problem shown here is probably the reason why multiple inheritance is unpopular in classic Python.

Why will this be a problem in the new system? The 'object' type at the top of the type hierarchy defines a number of methods that can usefully be extended by subtypes, for example __getattr__().

(Aside: in classic Python, the __getattr__() method is not really the implementation for the get-attribute operation; it is a hook that only gets invoked when an attribute cannot be found by normal means. This has often been cited as a shortcoming -- some class designs have a legitimate need for a __getattr__() method that gets called for all attribute references. But then of course this method has to be able to invoke the default implementation directly. The most natural way is to make the default implementation available as object.__getattr__(self, name).)

Thus, a classic class hierarchy like this:

class B     class C:
    ^         ^  def __getattr__(self, name): ...
     \       /
      \     /
       \   /
        \ /
      class D
      

will change into a diamond diagram under the new system:

      object:
        ^ ^  __getattr__()
       /   \
      /     \
     /       \
    /         \
class B     class C:
    ^         ^  def __getattr__(self, name): ...
     \       /
      \     /
       \   /
        \ /
      class D


and while in the original diagram C.__getattr__() is invoked, under the new system with the classic lookup rule, object.__getattr__() would be invoked!

Fortunately, there's a lookup rule that's better. It's a bit difficult to explain, but it does the right thing in the diamond diagram, and it is the same as the classic lookup rule when there are no diamonds in the inheritance graph (when it is a tree).

总结:Python2和Python3在关于面向对象的区别。

  • Py2:

    • 经典类,未继承object类型。【从左到右,深度优先,大小钻石,不留顶端】

      class Foo:
          pass
      
    • 新式类,直接获取间接继承object类型。【从左到右,深度优先,大小钻石,留住顶端 – C3算法】

      class Foo(object):
        pass
      

      class Base(object):
        pass
      
      class Foo(Base):
        pass
      
  • Py3

    • 新式类,丢弃了经典类只保留了新式类。【从左到右,深度优先,大小钻石,留住顶端 – C3算法】

      class Foo:
          pass
      
      class Bar(object):
          pass
      

2. 内置函数补充

本次要给讲解的内置函数共8个,他们都跟面向对象的知识相关。

  • classmethod、staticmethod、property 。

  • callable,是否可在后面加括号执行。

    • 函数

      def func():
          pass
      
      print( callable(func) ) # True
      
    • class Foo(object):
          pass
      
      print( callable(Foo) ) # True
      
    • 类中具有__call__方法的对象

      class Foo(object):
      	pass
      
      obj = Foo()
      print( callable(obj) ) # False
      
      class Foo(object):
      
          def __call__(self, *args, **kwargs):
              pass
          
      obj = Foo()
      print( callable(obj) ) # True
      

    所以当你以后在见到下面的情况时,首先就要想到handler可以是:函数、类、具有call方法的对象 这三种,到底具体是什么,需要根据代码的调用关系才能分析出来。

    def do_something(handler):
        handler()
    
  • super,按照mro继承关系向上找成员。

    class Top(object):
        def message(self, num):
            print("Top.message", num)
            
    class Base(Top):
        pass
    
    class Foo(Base):
    
        def message(self, num):
            print("Foo.message", num)
            super().message(num + 100)
    
    
    obj = Foo()
    obj.message(1)
    
    >>> Foo.message 1
    >>> Top.message 101
    
    class Base(object):
    
        def message(self, num):
            print("Base.message", num)
            super().message(1000)
    
    
    class Bar(object):
    
        def message(self, num):
            print("Bar.message", num)
    
    
    class Foo(Base, Bar):
        pass
    
    
    obj = Foo()
    obj.message(1)
    
    >>> Base.message 1
    >>> Bar.message 1000
    

    应用场景

    假设有一个类,他原来已实现了某些功能,但我们想在他的基础上再扩展点功能,重新写一遍?比较麻烦,此时可以用super。

    info = dict() # {}
    info['name'] = "武沛齐"
    info["age"] = 18
    
    value = info.get("age")
    
    print(value)
    
    class MyDict(dict):
    
        def get(self, k):
            print("自定义功能")
            return super().get(k)
    
    
    info = MyDict()
    info['name'] = "武沛齐" # __setitem__
    info["age"] = 18       # __setitem__
    print(info)
    
    value = info.get("age")
    
    print(value)
    

    在这里插入图片描述

  • type,获取一个对象的类型。

    v1 = "武沛齐"
    result = type(v1)
    print(result) # <class 'str'>
    
    v2 = "武沛齐"
    print( type(v2) == str )  # True
    
    v3 = [11, 22, 33] # list(...)
    print( type(v3) == list )  # True
    
    class Foo(object):
        pass
    
    v4 = Foo()
    
    print( type(v4) == Foo )  # True
    
  • isinstance,判断对象是否是某个类或其子类的实例。

    class Top(object):
        pass
    
    
    class Base(Top):
        pass
    
    
    class Foo(Base):
        pass
    
    
    v1 = Foo()
    
    print( isinstance(v1, Foo) )   # True,对象v1是Foo类的实例
    print( isinstance(v1, Base) )  # True,对象v1的Base子类的实例。
    print( isinstance(v1, Top) )   # True,对象v1的Top子类的实例。
    
    class Animal(object):
        def run(self):
            pass
    
    class Dog(Animal):
        pass
    
    class Cat(Animal):
        pass
    
    data_list = [
        "alex",
        Dog(),
        Cat(),
    	"root"
    ]
    
    for item in data_list:
        if type(item) == Cat:
            item.run()
        elif type(item) == Dog:
            item.run()
        else:
            pass
        
    for item in data_list:
        if isinstance(item, Animal):
            item.run()
        else:
            pass
    
  • issubclass,判断类是否是某个类的子孙类。

    class Top(object):
        pass
    
    
    class Base(Top):
        pass
    
    
    class Foo(Base):
        pass
    
    
    print(issubclass(Foo, Base))  # True
    print(issubclass(Foo, Top))   # True
    

3.异常处理

在程序开发中如果遇到一些 不可预知的错误 或 你懒得做一些判断 时,可以选择用异常处理来做。

import requests

while True:
    url = input("请输入要下载网页地址:")
    res = requests.get(url=url)
    with open('content.txt', mode='wb') as f:
        f.write(res.content)

上述下载视频的代码在正常情况下可以运行,但如果遇到网络出问题,那么此时程序就会报错无法正常执行。

try:
    res = requests.get(url=url)
except Exception as e:
    代码块,上述代码出异常待执行。
print("结束")
import requests

while True:
    url = input("请输入要下载网页地址:")
    
    try:
        res = requests.get(url=url)
    except Exception as e:
        print("请求失败,原因:{}".format(str(e)))
        continue
        
    with open('content.txt', mode='wb') as f:
        f.write(res.content)
num1 = input("请输入数字:")
num2 = input("请输入数字:")
try:
    num1 = int(num1)
    num2 = int(num2)
    result = num1 + num2
    print(result)
except Exception as e:
    print("输入错误")

以后常见的应用场景:

  • 调用微信的API实现微信消息的推送、微信支付等

  • 支付宝支付、视频播放等

  • 数据库 或 redis连接和操作

  • 调用第三方的视频播放发的功能,由第三方的程序出问题导致的错误。

异常处理的基本格式:

try:
    # 逻辑代码
except Exception as e:
    # try中的代码如果有异常,则此代码块中的代码会执行。
try:
    # 逻辑代码
except Exception as e:
    # try中的代码如果有异常,则此代码块中的代码会执行。
finally:
    # try中的代码无论是否报错,finally中的代码都会执行,一般用于释放资源。

print("end")

"""
try:
    file_object = open("xxx.log")
    # ....
except Exception as e:
    # 异常处理
finally:
    file_object.close()  # try中没异常,最后执行finally关闭文件;try有异常,执行except中的逻辑,最后再执行finally关闭文件。
"""    

3.1 异常细分

import requests

while True:
    url = input("请输入要下载网页地址:")
    
    try:
        res = requests.get(url=url)
    except Exception as e:
        print("请求失败,原因:{}".format(str(e)))
        continue
        
    with open('content.txt', mode='wb') as f:
        f.write(res.content)

之前只是简单的捕获了异常,出现异常则统一提示信息即可。如果想要对异常进行更加细致的异常处理,则可以这样来做:

import requests
from requests import exceptions

while True:
    url = input("请输入要下载网页地址:")
    try:
        res = requests.get(url=url)
        print(res)    
    except exceptions.MissingSchema as e:
        print("URL架构不存在")
    except exceptions.InvalidSchema as e:
        print("URL架构错误")
    except exceptions.InvalidURL as e:
        print("URL地址格式错误")
    except exceptions.ConnectionError as e:
        print("网络连接错误")
    except Exception as e:
        print("代码出现错误", e)
        
# 提示:如果想要写的简单一点,其实只写一个Exception捕获错误就可以了。

如果想要对错误进行细分的处理,例如:发生Key错误和发生Value错误分开处理。

基本格式:

try:
    # 逻辑代码
    pass

except KeyError as e:
    # 小兵,只捕获try代码中发现了键不存在的异常,例如:去字典 info_dict["n1"] 中获取数据时,键不存在。
    print("KeyError")

except ValueError as e:
    # 小兵,只捕获try代码中发现了值相关错误,例如:把字符串转整型 int("无诶器")
    print("ValueError")

except Exception as e:
    # 王者,处理上面except捕获不了的错误(可以捕获所有的错误)。
    print("Exception")

Python中内置了很多细分的错误,供你选择。

常见异常:
"""
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问n x[5]
KeyError 试图访问字典里不存在的键 inf['xx']
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的
"""
更多异常:
"""
ArithmeticError
AssertionError
AttributeError
BaseException
BufferError
BytesWarning
DeprecationWarning
EnvironmentError
EOFError
Exception
FloatingPointError
FutureWarning
GeneratorExit
ImportError
ImportWarning
IndentationError
IndexError
IOError
KeyboardInterrupt
KeyError
LookupError
MemoryError
NameError
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
ReferenceError
RuntimeError
RuntimeWarning
StandardError
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
ZeroDivisionError
"""

3.2 自定义异常&抛出异常

上面都是Python内置的异常,只有遇到特定的错误之后才会抛出相应的异常。

其实,在开发中也可以自定义异常。

class MyException(Exception):
    pass
try:
    pass
except MyException as e:
    print("MyException异常被触发了", e)
except Exception as e:
    print("Exception", e)

上述代码在except中定义了捕获MyException异常,但他永远不会被触发。因为默认的那些异常都有特定的触发条件,例如:索引不存在、键不存在会触发IndexError和KeyError异常。

对于我们自定义的异常,如果想要触发,则需要使用:raise MyException()类实现。

class MyException(Exception):
    pass


try:
    # 。。。
    raise MyException()
    # 。。。
except MyException as e:
    print("MyException异常被触发了", e)
except Exception as e:
    print("Exception", e)
class MyException(Exception):
    def __init__(self, msg, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.msg = msg


try:
    raise MyException("xxx失败了")
except MyException as e:
    print("MyException异常被触发了", e.msg)
except Exception as e:
    print("Exception", e)
class MyException(Exception):
    title = "请求错误"


try:
    raise MyException()
except MyException as e:
    print("MyException异常被触发了", e.title)
except Exception as e:
    print("Exception", e)

案例一:你我合作协同开发,你调用我写的方法。

  • 我定义了一个函数

    class EmailValidError(Exception):
        title = "邮箱格式错误"
    
    class ContentRequiredError(Exception):
        title = "文本不能为空错误"
        
    def send_email(email,content):
        if not re.match("\w+@live.com",email):
            raise EmailValidError()
    	if len(content) == 0 :
            raise ContentRequiredError()
    	# 发送邮件代码...
        # ...
    
  • 你调用我写的函数

    def execute():
        # 其他代码
        # ...
        
    	try:
            send_email(...)
        except EmailValidError as e:
            pass
        except ContentRequiredError as e:
            pass
        except Exception as e:
            print("发送失败")
    
    execute()
    
    # 提示:如果想要写的简单一点,其实只写一个Exception捕获错误就可以了。
    

案例二:在框架内部已经定义好,遇到什么样的错误都会触发不同的异常。

import requests
from requests import exceptions

while True:
    url = input("请输入要下载网页地址:")
    try:
        res = requests.get(url=url)
        print(res)    
    except exceptions.MissingSchema as e:
        print("URL架构不存在")
    except exceptions.InvalidSchema as e:
        print("URL架构错误")
    except exceptions.InvalidURL as e:
        print("URL地址格式错误")
    except exceptions.ConnectionError as e:
        print("网络连接错误")
    except Exception as e:
        print("代码出现错误", e)
        
# 提示:如果想要写的简单一点,其实只写一个Exception捕获错误就可以了。

案例三:按照规定去触发指定的异常,每种异常都具备被特殊的含义。

在这里插入图片描述

3.4 特殊的finally

try:
    # 逻辑代码
except Exception as e:
    # try中的代码如果有异常,则此代码块中的代码会执行。
finally:
    # try中的代码无论是否报错,finally中的代码都会执行,一般用于释放资源。

print("end")

当在函数或方法中定义异常处理的代码时,要特别注意finally和return。

def func():
    try:
        return 123
    except Exception as e:
        pass
    finally:
        print(666)
        
func()

在try或except中即使定义了return,也会执行最后的finally块中的代码。

4.反射

反射,提供了一种更加灵活的方式让你可以实现去 对象 中操作成员(以字符串的形式去 对象 中进行成员的操作)。

class Person(object):
    
    def __init__(self,name,wx):
        self.name = name
        self.wx = wx
	
    def show(self):
        message = "姓名{},微信:{}".format(self.name,self.wx)
        
        
user_object = Person("武沛齐","wupeiqi666")


# 对象.成员 的格式去获取数据
user_object.name
user_object.wx
user_object.show()

# 对象.成员 的格式无设置数据
user_object.name = "吴培期"
user = Person("武沛齐","wupeiqi666")

# getattr 获取成员
getattr(user,"name") # user.name
getattr(user,"wx")   # user.wx


method = getattr(user,"show") # user.show
method()
# 或
getattr(user,"show")()

# setattr 设置成员
setattr(user, "name", "吴培期") # user.name = "吴培期"

Python中提供了4个内置函数来支持反射:

  • getattr,去对象中获取成员

    v1 = getattr(对象,"成员名称")
    v2 = getattr(对象,"成员名称", 不存在时的默认值)
    
  • setattr,去对象中设置成员

    setattr(对象,"成员名称",值)
    
  • hasattr,对象中是否包含成员

    v1 = hasattr(对象,"成员名称") # True/False
    
  • delattr,删除对象中的成员

    delattr(对象,"成员名称")
    

以后如果再遇到 对象.成员 这种编写方式时,均可以基于反射来实现。

案例:

class Account(object):

    def login(self):
        pass

    def register(self):
        pass

    def index(self):
        pass

    
def run(self):
    name = input("请输入要执行的方法名称:") # index register login xx run ..
    
    account_object = Account()
    method = getattr(account_object, name,None) # index = getattr(account_object,"index")
    
    if not method:
        print("输入错误")
        return 
    method()

4.1 一些皆对象

在Python中有这么句话:一切皆对象。 每个对象的内部都有自己维护的成员。

  • 对象是对象

    class Person(object):
        
        def __init__(self,name,wx):
            self.name = name
            self.wx = wx
    	
        def show(self):
            message = "姓名{},微信:{}".format(self.name,self.wx)
            
            
    user_object = Person("武沛齐","wupeiqi666")
    user_object.name
    
  • 类是对象

    class Person(object):
        title = "武沛齐"
    
    Person.title
    # Person类也是一个对象(平时不这么称呼)
    
  • 模块是对象

    import re
    
    re.match
    # re模块也是一个对象(平时不这么称呼)。
    

由于反射支持以字符串的形式去对象中操作成员【等价于 对象.成员 】,所以,基于反射也可以对类、模块中的成员进行操作。

简单粗暴:只要看到 xx.oo 都可以用反射实现。

class Person(object):
    title = "武沛齐"

v1 = Person.title
print(v1)
v2 = getattr(Person,"title")
print(v2)
import re

v1 = re.match("\w+","dfjksdufjksd")
print(v1)

func = getattr(re,"match")
v2 = func("\w+","dfjksdufjksd")
print(v2)

4.2 import_module + 反射

在Python中如果想要导入一个模块,可以通过import语法导入;企业也可以通过字符串的形式导入。

示例一:

# 导入模块
import random

v1 = random.randint(1,100)
# 导入模块
from importlib import import_module

m = import_module("random")

v1 = m.randint(1,100)

示例二:

# 导入模块exceptions
from requests import exceptions as m
# 导入模块exceptions
from importlib import import_module
m = import_module("requests.exceptions")

示例三:

# 导入模块exceptions,获取exceptions中的InvalidURL类。
from requests.exceptions import InvalidURL
# 错误方式
from importlib import import_module
m = import_module("requests.exceptions.InvalidURL") # 报错,import_module只能导入到模块级别。
# 导入模块
from importlib import import_module
m = import_module("requests.exceptions")
# 去模块中获取类
cls = m.InvalidURL

在很多项目的源码中都会有 import_modulegetattr 配合实现根据字符串的形式导入模块并获取成员,例如:

from importlib import import_module

path = "openpyxl.utils.exceptions.InvalidFileException"

module_path,class_name = path.rsplit(".",maxsplit=1) # "openpyxl.utils.exceptions"   "InvalidFileException"

module_object = import_module(module_path)

cls = getattr(module_object,class_name)

print(cls)

我们在开发中也可以基于这个来进行开发,提高代码的可扩展性,例如:请在项目中实现一个发送 短信、微信 的功能。

总结

  1. 了解 mro和c3算法

  2. python2和python3在面向对象中的区别。

  3. 内置函数

    staticmethod,classmethod,property,callable,type,isinstance,issubclass,super
    getattr,setattr,hasattr,delattr
    
  4. 异常处理

  5. 根据字符串的形式导入模块 import_module

  6. 根据字符串的形式操作成员 反射-getattr,setattr,hasattr,delattr

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/349279.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue3---inputRef.value.focus()报错Cannot read properties of null (reading ‘focus‘)

问题描述&#xff1a;点击编辑按钮&#xff0c;出现el-input框&#xff08;el-input显示隐藏通过v-if控制&#xff09; <el-input ref"inputRef" v-if"isEdit" v-model"modelName" blur"isEdit false" /> <el-button text …

python-自动化篇-办公-excel-实例应用(一维转二维)

文章目录 准备代码效果 准备 放根目录 代码 import openpyxl wbopenpyxl.load_workbook(业绩表.xlsx) if not 二维表 in wb.sheetnames:nwswb.create_sheet(二维表)wswb.worksheets[0]rngslist(ws.values)[1:]mmlist({m.value: for m in ws[b][1:]})namelist({m.value: for …

(2)(2.8) Holybro 900Mhz XBP9X无线电遥测设备

文章目录 前言 1 特点 2 规格 3 电源 4 引脚输出 5 下载 前言 Holybro XBP9X 无线电设备可使用 Digi 免费的 XCTU 软件或通过 Digi 简化的 AT 或 API 命令集轻松进行配置。无线电台采用 256 位 AES 加密技术&#xff0c;可在设备之间安全可靠地传输关键数据。无线电的射…

基于Kubernetes(K8s)构建企业容器云基础运行环境

cncfstack 新 文章上线&#xff1a; 书名&#xff1a;《云原生解决方案》 地址&#xff1a;https://zhaowenyu.com/cncf-solution 访问&#xff1a;文章底部“阅读原文”或访问域名 云原生计算是云计算发展新的里程碑阶段&#xff0c;是当今与未来很长一段时间中 IT 发展的技…

代码随想录 Leetcode111. 二叉树的最小深度

题目&#xff1a; 代码(首刷自解 2024年1月24日&#xff09;&#xff1a; class Solution { public:int minDepth(TreeNode* root) {if(root nullptr) return 0;queue<TreeNode*> que;TreeNode* cur root;que.push(cur);int size 0;int depth 0;while (!que.empty()…

Tomcat session复制及session共享技术

目录 1、环境 2、配置测试页面 3、配置session共享 前言&#xff1a; 为什么要做session复制或共享 实现Session复制或Session共享的目的是为了在多个Tomcat实例之间实现Session的无缝转移和共享&#xff0c;以提供更高的可伸缩性、负载均衡和容错性。以下是一些原因&#x…

C语言基本概念

目录 2.1 编写一个简单的C程序 2.1.1 编译和链接 2.1.2 集成开发环境 2.2 简单程序的一般形式 2.2.1 指令 2.2.2 函数 2.2.3 语句 2.3 注释 2.4 变量和赋值 2.4.1 类型 2.4.2 声明 2.4.3 赋值 2.4.4 显示变量的值 2.4.5 初始化 2.4.6 显示表达式的值 2.5 读入…

7款值得去尝试的前端动画特效(附效果图及在线演示)

分享7款好玩的前端动画特效 其中有CSS动画、canvas动画、js小游戏等等 下方效果图可能不是特别的生动 那么你可以点击在线预览进行查看相应的动画特效 同时也是可以下载该资源的 橙汁粒子特效 一款基于canvas实现的粒子动画特效 点击杯子 杯子上方会有橙子掉落至杯中并变为橙…

如何做标准化?| 京东云技术团队

在现代信息化的市场环境和社会中&#xff0c;标准化已经成为了各种行业的一个重要的标志。标准化不仅可以提升生产效率&#xff0c;减轻质量问题&#xff0c;还可以增加产品的可靠性和互通性。在这篇文章中&#xff0c;我们将探讨如何做标准化&#xff0c;为您提供详细的指导和…

深入理解Java类和对象的关系

如果要说清楚对象和类的关系&#xff0c;不可避免的要提到C&#xff0c;因为Java从时间线上来说&#xff0c;是C和C之后的一门语言&#xff0c;很多Java Coder 也是因为厌烦了C的一些特性&#xff0c;进而从事于Java开发的&#xff0c;所以以下内容会利用C的一部分知识来对比&a…

Mac+Android Studio配置 Flutter环境

Fluttrer中文下载官网 Flutter下载官网 1、环境变量 .zshrc #Flutter export PUB_HOSTED_URL"https://pub.flutter-io.cn" export FLUTTER_STORAGE_BASE_URL"https://storage.flutter-io.cn" export FLUTTER_HOME/Users/leon/Flutter/flutter_3_10_4/f…

【C/C++】C/C++编程——第一个 C++ 程序:HelloWorld

第一个 C 程序&#xff1a;HelloWorld 大家好&#xff0c;我是 shopeeai&#xff0c;也可以叫我虾皮&#xff0c;中科大菜鸟研究生。昨天我们成功搭建好了 C 的开发环境&#xff0c;今天我们来介绍一下第一个 C 程序,打印一个"hello world"。首先我们先贴一下示例代…

Linux(linux版本 centos 7) 下安装 oracle 19c详细教程(新手小白易上手)

一、安装前准备 1、下载预安装包 wget http://yum.oracle.com/repo/OracleLinux/OL7/latest/x86_64/getPackage/oracle-database-preinstall-19c-1.0-1.el7.x86_64.rpm预安装包下载成功 2、下载oracle安装包 下载地址如下 https://www.oracle.com/cn/database/technologies…

Python 正则分割字符串并提取匹配的记号和关键词

需求是&#xff1a;原字符串内含有特殊记号&#xff0c;比如"V_{CC} V_{DD}"&#xff0c;其中_{CC} 是latex 的下标语法&#xff0c;实际显示出来是下面这样&#xff1a; V C C V D D V_{CC} V_{DD} VCC​VDD​ 现在要把下标部分提取出来&#xff0c;并把原字符串…

Python之数据可视化基础

目录 一 JSON数据格式转换 二 pyecharts模块 三 Pyecharts入门 四 数据可视化之疫情折线图 一 JSON数据格式转换 什么是JSON? JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式。它以易于阅读和编写的方式来表示结构化数据。JSO…

构建未来学堂:在线教育系统开发技术实践

在当今数字化时代&#xff0c;在线教育系统的开发越发显得至关重要。本文将带你深入了解在线教育系统的开发&#xff0c;涉及到关键的技术实践和代码示例。我们将采用现代化技术栈&#xff0c;为未来学堂的搭建提供实用的指南。 技术栈选择 在开始实际的开发之前&#xff0c…

在IDEA中创建SpringBoot项目

概述 SpringBoot是由Pivotal团队提供的全新的框架&#xff0c;其设计的目的是用来简化Spring应用的初始搭建以及开发过程。 传统方式构建Spring应用程序 导入依赖繁琐 依赖冲突 项目配置繁琐 SpringBoot特性 1、起步依赖 本质上就行一个Maven坐标&#xff0c;整合了完成一…

虚幻UE 插件-像素流送实现和优化

本笔记记录了像素流送插件的实现和优化过程。 UE version&#xff1a;5.3 文章目录 一、像素流送二、实现步骤1、开启像素流送插件2、设置参数3、打包程序4、打包后的程序进行像素流参数设置5、下载NodeJS6、下载信令服务器7、对信令服务器进行设置8、启动像素流送 三、优化1、…

机电制造ERP软件有哪些品牌?哪家的机电制造ERP系统比较好

机电制造过程比较复杂&#xff0c;涵盖零配件、采购、图纸设计、工艺派工、生产计划、物料需求计划、委外加工等诸多环节。而供应链涉及供应商的选择、材料采购价格波动分析、材料交货、品质检验等过程&#xff0c;其中某个环节出现问题都可能会影响产品交期和经营效益。 近些…

设计模式_组合模式_Composite

案例引入 学校院系展示 编写程序展示一个学校院系结构: 需求是这样&#xff0c;要在一个页面中展示出学校的院系组成&#xff0c;一个学校有多个学院&#xff0c;一个学院有多个系 【传统方式】 将学院看做是学校的子类&#xff0c;系是学院的子类&#xff0c;小的组织继承大…