Python基础学习(4)编程范式、反射、面向对象、接口、异常处理

1. 编程范式

1)面向过程

核心是过程,过程指的是解决问题的步骤。设计一套流水线,根据业务逻辑从上到下写代码,是一种机械式的思维方式。将某个功能代码封装到函数中,日后便无需重复填写,仅调用函数即可

优点:复杂的问题流程化,进而简单化

缺点:可扩展性差

2)面向对象

核心就是对象,对象就是特征与技能的结合体。对函数进行分类和封装,让开发“更快更好更强···”

优点:可扩展性强

缺点:编程复杂度高

用户场景:用户需求经常变化,互联网应用、游戏



2. 反射

通过字符串的形式倒入模块

通过字符串的形式去模块中寻找指定函数,并执行

如果是类:只能找类里的成员

如果是反射:既可以找对象,也可以找类的成员

简单案例1:

# 根据用户输入的内容,导入模块
inp = input("请输入模块名: ")

# __import__ 用于以字符串的形式导入模块
mod = __import__(inp) # 相当于用import引入函数

# 模块中寻找函数并执行函数
inp_func = input("请输入要执行的函数: ")
# getattr用于以字符串的形式去某个模块中寻找函数
target_func = getattr(mod, inp_func, None) # 第三个参数为默认值,防止在模块中没有找到方法而报错
# 将获取到的函数名后加()表示,执行函数
result = target_func()
print(result)

案例2,根据类创建对象:

# 导入模块
m = __import__("test", fromlist=True)
# 去模块中找类
class_name = getattr(m, "Foo")
# 根据类创建对象
obj = class_name("Steve")
# 去对象中找name对应的值
val = getattr(obj, "name")
print(name)

1) getattr(input_module, input_function, None) # 获取模块中的方法

2) hasattr(input_module, input_function) # 根据字符串的形式去某各个模块中判断东西是否存在

3) setattr(input_module, "global_var", 1) # 设置模块的全局变量或函数

setattr(inout_module, "func1", lambda x : x**2)

4) delattr(input_module, "func1") # 去某个模块中删除变量或方法

5) 导入模块

mod = __import__(module_name)

mod = __import__("lib.test.com", fromlist = True) 

模拟web框架的案例:

# 输入模块与方法名
target_module, target_func = input("请输入url: ").split("/")

m = __import__(target_module, fromlist=True)

if hasattr(m, target_func):
    target_func = getattr(m, target_func)
    r = target_func()
    print(r)
else:
    print("404")



2. 面向对象

类:一系列对象相似的特征与技能的结合体

类中数据属性,是所有对象共有的

类中函数属性,是绑定给对象,绑定到不同的对象是不同的绑定方法


1) 面向对象编程

a. 定义类

class student:
    school = 'OT'
    def learn(self):
        print('Learn')
    def eat(self):
        print('Eat')
    def sleep(self):
        print('Sleep')

class 类名:

    def 方法1(self, args):

        pass

b. 根据类创建对象

stu1 = student()

使用对象去执行类中方法


2) self,形式参数,python内部传递。执行方法,执行过程中可以根据self去obj1中去取已经封装在里面的数据


3) 类+括号 =》自动执行类中的__init__方法

在__init__方法中执行具体封装的操作

__init__有一个特殊名字:构造方法

==》 初始化


4)

(1) __del__,解释器销毁对象时自动调用,特殊的名:析构方法

(2)__dict__,查看类的名称空间,

查: print(student.__dict__['school']); student.school

增:student.age = 19

删:del student.age

改:student.school = "TT"


5) 封装

使用场景:当同一类型的方法具有相同参数时,直接封装到对象即可

使用场景:把类当作模板,创建多个对象(对象内封装的数据可以不一样)


6) 继承与派生

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

派生类和基类同时存在,优先找派生类

继承的子类会先于父类被检查

多个父类会根据他们在列表中的顺序被检查

如果对下一个类存在两个合法的选择,选择第一个父类

Python类可以同时继承多个类,优先级:自己、左边、右边

新式类:广度优先

经典类:深度优先

继承父类的构造方法案例:

class Animal:
    def __init__(self):
        print("Animal")

class Cat(Animal):
    def __init__(self):
        print("Cat")
        super(Cat, self).__init__()

c = Cat()

7) 多态,多种形态,Python本身支持多态

多态性:指的是可以在不考虑对象的类型的情况下,而直接使用对象

优点:增加了程序的灵活性;增加了程序的可扩展性


8) 重载,函数名相同,参数个数不同

重写,派生类中重新实现基类中的方法


9) 静态方法与静态字段,静态方法无需使用对象封装的内容

通过类访问有:静态字段、静态方法

通过对象访问:普通字段,类的方法

class Province:
    # 静态字段
    country = "China"

    def __init__(self):
        pass

    def show(self):
        pass

    # 静态方法
    @ staticmethod
    def play():
        print("Static method")


# 自己去访问自己的成员
print(Province.country)

# 通过类直接访问静态访问
Province.play()


10) 类方法,相当于特殊的静态方法

class Province:

    def __init__(self):
        pass

    # 类方法,至少要有个class参数
    @ classmethod
    def show(cls):
        print("Class method")

Province.show()


11) 特性property,将方法伪造成一种字段,无需加括号来访问方法,但也无法添加参数

class Person:

    def __init__(self,name):
        self.name = name

    # 特性,用来获取
    @property
    def hello(self):
        return "Hello %s!" % self.name

    # 设置
    @hello.setter
    def hello(self, name):
        self.name = name
        return "Hello %s!" % self.name

p = Person("Dante")
print(p.hello)
p.hello = "Nero"
print(p.hello)


12) 成员修饰符

成员:普通字段、静态字段、普通方法、静态方法、类方法、普通特性
class Account:
    # 普通字段,可以从外部访问
    balance = 100
    # 私有字段,无法从外部直接访问
    __credit = 200

    def __init__(self,balance):
        self.balance = balance

    def withdaraw(self, amount):
        self.balance -= amount
        return self.balance

    def save(self, amount):
        self.balance += amount
        return self.balance

    # 私有方法
    def __set_credit(self, credit):
        self.__credit = credit


# 可以通过以下方式访问私有字段:对象+一个下划线+私有方法名
a1 = Account(1000)
print(a1._Account__credit)


13) 类的特殊成员call

class Test:
    def __init__(self):
        print("init")

    def __call__(self, *args, **kwargs):
        print("call")
        return 1

t = Test()()
print(t)


14) 类的特殊成员setitem,getitem,delitem

class Test:
    def __init__(self):
        print("init")

    def __call__(self, *args, **kwargs):
        print("call")
        return 1

    # getitem方法
    def __getitem__(self, item):
        print(item)

    # setitem方法
    def __setitem__(self, key, value):
        print(key, value)

    # delitem方法
    def __delitem__(self, key):
        print(key)

t = Test()
# 对象加中括号会自动执行__getitem__()方法
t["k1"]
# 对象加中括号赋值,会自动执行__setitem__()方法
t["k2"] = "Steve"
# 在对象上用del方法加中括号,会自动执行__delitem__()方法
# del t["k1"]
# 类似切片操作时,会执行以下方法:__getslice__ / __getitem__
t[1:3]
# 类似切片赋值的操作会执行以下方法:__setslice__ / __setitem__
t[1:3] = [1,2,3]
# 类似切片删除的操作时会执行以下方法:__delslice__ / __delitem__
del t[1:3]


15) 类的特殊成员dict

class Test:
    def __init__(self):
        self.name = "Steve"

    def __call__(self, *args, **kwargs):
        print("call")
        return 1

t = Test()
# 获取对象的信息
print(t.__dict__)
# 获取类的信息
print(Test.__dict__)


16) 类的特殊成员iter

class Test:
    def __iter__(self):
        for i in range(10):
            yield i


t = Test()

# for循环会自动执行类中的__iter__(self)方法
for i in t:
    print(i)


17) 抽象类

import abc
class Animal(metaclass=abc.ABCMeta): # 只能被继承,不能被实例化
    @abc.abstractmethod
    def run(self):
        pass
    @abc.abstractmethod
    def eat(self):
        pass

class People(Animal):
    def run(self):
        print("People is running")
    def eat(self):
        print("People is eating")


18)封装之隐藏

class A:
    __x = 1
    def __init__(self,name):
        self.__name = name # self._A__name = name
    def __foo(self):
        print('foo')
    def bar(self):
        self.__foo()
        print('from bar')

这种变形的特点:

(1)在类内部无法直接访问

(2)在内部是可以直接使用

(3)子类无法覆盖父类__开头的属性


这种变性需要注意的问题:

(1)这种机制并没有真正意义上限制我们从外部直接访问属性,a._A__N便可访问

(2)变形的过程只在类的定义时发生一次,在定义后的赋值操作,不会变形

(3)在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的


封装的意义:

封装数据属性:明确地区分内外,控制外部对隐藏属性的操作

封装方法:隔离复杂度


19)单例模式

class MySQL:
    __instance = None
    
    def __init__(self):
        self.host = '127.0.0.1'
        self.port = 3306
    
    @classmethod
    def singleton(cls):
        if not ls.__instance:
            obj = cls()
            cls.__instance = obj
        return ls.__instance

    def conn(self):
        pass

    def execute(self):
        pass

obj1 = MySQL.singleton()




4. 接口,interface,在接口中写方法,但不实现具体的方法

interface IFather:
    def fun1(self):pass
    def fun2(self):pass


5. 异常处理

简单的异常处理案例:

inp = input("Please input an integer: ")

try:
    num = int(inp)
    print(num)
except Exception as e:
    # 如果出错,将错误信息打印出来
    print(e)


1) python中的常用异常种类

AttributeError: 试图访问一个对象没有的属性

IOError: 输入/输出异常,基本上是无法打开文件

ImportError:无法引入模块或包,基本上是路径问题或名称错误

IndentationError:语法错误(的子类),代码没有正确对齐

IndexError:下标索引超出序列边界

KeyError:试图访问字典里不存在的键

KeyboardInterrupt: Ctrl + C 被按下

NameError:使用一个还未被赋予对象的变量
SyntaxError:python代码非法,代码不能编译

TypeError: 出入对象类型与要求的不符合

UnboundLocalError: 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致以为在访问它

ValueError:传入一个调用者不期望的值,即使值的类型是正确的

Exception:所有错误类的基类


2)完整的异常代码块

try:
    # 主代码块
    pass
except Exception as e:
    # 异常时,执行该块
    pass
else:
    # 主代码块执行完,执行该块
    pass
finally:
    # 无论异常与否,最终执行该块
    pass


3)主动触发异常

try:
    raise Exception("Error raised")
except Exception as e:
    print(e)


4)断言

a = 1
# 条件不成立则报错,一般用来测试条件是否成立
assert a > 2


5)多分支

s1 = 'hello'
try:
    int(s1)
except IndexError as e:
    print(e)
except KeyError as e:
    print(e)
except ValueError as e:
    print(e)


6)自定义异常类型

class MyException(BaseException):
    def __init__(self, msg):
        super(MyException, self).__init__()
        self.msg = msg


5. 单例模式,只有一个实例,通过静态方法+静态字段实现

所有的实例中封装的内容相同时,用单例模式

简单案例:

class ConnectionPool:

    __instance = None

    def __init__(self):
        self.ip = "127.0.0.0"
        self.port = 3306
        self.username = "root"
        self.pwd = "root"

        # 去连接,假设建立了10个连接
        self.conn_list = [1,2,3,4,5,6,7,8,9,10]

    @staticmethod
    def getInstance(self):
        if ConnectionPool.__instance:
            return ConnectionPool.__instance
        else:
            ConnectionPool.__instance = ConnectionPool()
            return ConnectionPool.__instance

    def get_conection(self):
        # 获取连接
        import random
        num = random.randint(1,11)
        return num


for i in range(10):
    pool = ConnectionPool.getInstance()
    print("去连接池", pool, "中获取一个连接")
    conn = pool.get_conection()
    print("获取到的是连接: ", conn)



猜你喜欢

转载自blog.csdn.net/wayne12081213/article/details/78936974