python学习09

面向对象

1.单例模式

目的是为了确保某一类只有一个实例存在。我们可以使用__new__来控制实例的创建过程,代码如下:

class Singleton(object):
    _instace=None   #做一个标识 如果等于None说明还没被创建过
    def __new__(cls, *args, **kwargs):
        print('__new__')
        if cls._instace == None:
            cls._instace = object.__new__(cls)
            return cls._instace
        else:
            return cls._instace

s1=Singleton()
s2=Singleton()
s3=Singleton()
print(id(s1))
print(id(s2))
print(id(s3))
#以上输出得到的ID地址为同一个,证明单例创建成功

在上面的代码中,我们将类的实例和一个类变量_instance关联起来,如果cls._instance为None则创建实例,否则直接返回cls._instance。

2.工厂模式(Simple Factory Pattern)

是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类 并且重写父类方法。

采用简单工厂的优点是可以使用户根据参数获得对应的类实例,避免了直接实例化类,降低了耦合性;

缺点是可实例化的类型在编译期间已经被确定,如果增加新类型,则需要修改工厂,不符合OCP(开闭原则)的原则。

(OCP原则:一个软件应用对扩展开放,对修改关闭)

多态:不同的类对同一个消息/动作做出不同的解释,执行不一样的代码
3个必要条件
1.发生继承关系
2.子类重写父类方法
3.里氏代换原则

好处:节省代码 更符合现实逻辑

下面我们看一个例子:

要求输入两个数和一个运算符,进行四则运算并输出得到结果。

类的结构图:


class Operation:    #父类
    def __init__(self,num1,num2):
        self.num1=num1
        self.num2=num2
    def yunsuan(self):
        pass

class   OperationAdd(Operation):
    def __init__(self,num1,num2):
        super().__init__(num1,num2)
    def yunsuan(self):
        return self.num1 + self.num2

class   OperationSub(Operation):
    def __init__(self,num1,num2):
        super().__init__(num1,num2)
    def yunsuan(self):
        return self.num1 - self.num2

class   OperationMul(Operation):
    def __init__(self,num1,num2):
        super().__init__(num1,num2)
    def yunsuan(self):
        return self.num1 * self.num2

class   OperationDiv(Operation):
    def __init__(self,num1,num2):
        super().__init__(num1,num2)
    def yunsuan(self):
        return self.num1 // self.num2

#工厂类
class OperationFactory(object):
    @classmethod       #classmethod可以通过类方法调用类属性,也可以通过对象调用类属性
    def getOperation(self,fu,num1,num2):     #getOperation获取运算符
        if '+'.__eq__(fu):
            return OperationAdd(num1,num2)
        elif '-'.__eq__(fu):
            return OperationSub(num1,num2)
        elif '*'.__eq__(fu):
            return OperationMul(num1,num2)
        elif '/'.__eq__(fu):
            return OperationDiv(num1,num2)

if '__main__' == __name__:
    num1=int(input('第一个数'))
    num2=int(input('第二个数'))
    fu=input('操作符')
    #父类类型 容纳子类对象 ->里氏代换原则
    operation=OperationFactory.getOperation(fu,num1,num2)
    js=operation.yunsuan()
    print('运算结果:',js)

isinstance()函数 判断是否 继承关系 某一个变量是否是某一个数据类型。

上述程序如想输出 判断的哪种继承关系,则可在后面添加以下代码:

    if isinstance(operation,OperationAdd):
        print('创建是的是OperationAdd类型')
    elif isinstance(operation,OperationSub):
        print('创建是的是OperationSub类型')
    elif isinstance(operation,OperationMul):
        print('创建是的是OperationMul类型')
    elif isinstance(operation,OperationDiv):
        print('创建是的是OperationDiv类型')

1).__getattribute__()  访问属性(类名,对象名)

2).__setattr__()   添加属性

3).hasattr(name,str) 判断属性是否存在

在上述工厂中使用这三个函数:

    oper=OperationFactory.getOperation('+',6,6)
    print(oper.__getattribute__('num1'))
    oper.__setattr__('num3',5)
    print(oper.__getattribute__('num3'))   #得到5
    print(hasattr(oper,'num3')) #返回True
    #若是print(hasattr(oper,'num4')),会返回Flase,因为并没有num4属性

我们还可以给类(只能在类级别添加,所有对象通用,不能给对象添加)动态添加函数,所有对象都能用 。如下:

#继续使用上面的OperationFactory类
#在同级别编写函数
set getName(self,name):
    self.getName=name
#给类添加  一旦类添加了,所有对象都能调用,函数不支持给直接给对象添加
OperationFactory.setName=setName
oper=OperationFactory.getOperation('+',6,6)
oper.setName='加法'
print('运算方式为:',open.setName)
#输出得到:运算方式为:加法

4).__slots__变量

为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,

来限制该class实例能添加的属性 。例如:

class a():
    __slots__ = ('name','age')   #限制只能添加'name'和'age'属性
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def show(self):
        print('名字是:',self.name,' 年龄是:'+str(self.age))

if '__main__' == __name__:
    b=a('汪汪',6)
    b.c='w'
    b.show() 
    print(b.c)  #因为限制,只允许name 和age ,无法输出c,所有会报错

5).@property

在我们对类属性做一些修改时,需要使用get和set来实现,我们可以使用@property来实现减少代码编写,减少错误的发生。

使用如下:

class Name():
    @property
    def Age(self):      #注意,属性名必须一致,如都为Age
        return self.age

    @Age.setter
    def Age(self, age):
        if age<0 or age>100:
            print('超出范围,默认18')
            self.age=18
        else:
            self.age=age
            print(self.age)

name=Name()
name.Age=199    #输出 超出范围,默认180

6).__call__()

__call__()可以使一个类实例变成一个可调用对象。如下:

class Person(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

    def __call__(self, friend):
        print('My name is %s...' % self.name)
        print('My friend is %s...' % friend)

p = Person('Bob', 'male')
p('Tim')     #直接调用
#输出 My name is Bob...
#输出 My friend is Tim...

7).callable()

callable() 函数用于检查一个对象是否是可调用的。

callable(0)
#False
def add(a, b):
    return a + b

callable(add)             # 函数返回 True
#True
class A:                  # 类
    def method(self):
            return 0

callable(A)               # 类返回 True
#True








猜你喜欢

转载自blog.csdn.net/gy_334/article/details/80324911