Python——面向对象(2)

本文详细介绍了Python中的面向对象编程概念,包括继承、方法重写、多态以及类属性和实例属性。通过实例展示了如何创建类、定义方法,以及如何利用继承实现类的层级结构。同时,探讨了类方法和静态方法的区别,并通过单例模式的应用来展示其在实际编程中的用途。
摘要由CSDN通过智能技术生成

1.继承

在现实生活中,继承一般指的是子女继承父辈的财产,在程序中,继承描述的是事物之间的所属关系,例如猫和狗都属于动物,程序中便可以描述为猫和狗继承自动物

子类在继承的时候,在定义类时,小括号()中为父类的名字
父类的属性、方法,会被继承给子类

class Animal:
    def eat(self):
        print("-----吃----")
    def drink(self):
        print("-----喝----")
    def sleep(self):
        print("-----睡觉----")
    def run(self):
        print("-----跑----")
class Dog(Animal):
    def bark(self):
        print("----叫---")
class Cat(Animal):
    def catch(self):
        print("----抓老鼠----")
#a = Animal()
#a.eat()
wangcai = Dog()
wangcai.eat()

tom = Cat()
tom.eat()

python中是可以多继承的,所谓多继承,即子类有多个父类,并且具有它们的特征

# 定义一个父类
class A:
    def printA(self):
        print('----A----')

# 定义一个父类
class B:
    def printB(self):
        print('----B----')

# 定义一个子类,继承自A、B
class C(A,B):
    def printC(self):
        print('----C----')

obj_C = C()
obj_C.printA()
obj_C.printB()

如果多个父类中,有一个同名的方法,那么通过子类去调用的该方法的时候,和类的对象搜索方法时的先后顺序有关

class A():
    def test(self):
        print('----A test----')

# 定义一个父类
class B():
    def test(self):
        print('----B test----')

# 定义一个子类,继承自A、B
class C(B,A):
    pass
obj_C = C()
obj_C.test()

print(C.__mro__) #可以查看C类的对象搜索方法时的先后顺序

2.方法重写

所谓重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法

class Cat(object):
    def sayHello(self):
        print("halou-----1")

class Bosi(Cat):

    def sayHello(self):
        print("halou-----2")

bosi = Bosi()

bosi.sayHello()

调用父类的方法

语法格式:
父类类名.父类的方法(self)
super(子类的类名,self).方法名()
super().父类的方法名()

class Cat(object):
    def __init__(self,name):
        print(name)

class Bosi(Cat):

    def __init__(self,name):
        # 调用父类的__init__方法1
        #Cat.__init__(self,name)
        # 调用父类的__init__方法2
        #super(Bosi,self).__init__(name)
        # 调用父类的__init__方法3
        super().__init__(name)

3.多态

所谓多态:定义时的类型和运行时的类型不一样,此时就成为多态
多态的概念是应用于Java和C#这一类强类型语言中,而Python崇尚“鸭子类型”。
Python伪代码实现Java或C#的多态

class F1(object):
    def show(self):
        print('F1.show')

class S1(F1):
    def show(self):
        print('S1.show')

class S2(F1):
    def show(self):
        print('S2.show')
# 由于在Java或C#中定义函数参数时,必须指定参数的类型
# 为了让Func函数既可以执行S1对象的show方法,又可以执行S2对象的show方法,所以,定义了一个S1和S2类的父类
# 而实际传入的参数是:S1对象和S2对象

def Func(obj):
    """Func函数需要接收一个F1类型或者F1子类的类型"""
    obj.show()

s1_obj = S1()
Func(s1_obj) # 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show

s2_obj = S2()
Func(s2_obj) # 在Func函数中传入S2类的对象 s2_obj,执行 S2 的show方法,结果:S2.show


Python “鸭子类型”
class F1(object):
    def show(self):
        print('F1.show')

class S1(F1):

    def show(self):
        print('S1.show')

class S2(F1):

    def show(self):
        print('S2.show')

def Func(obj):
    obj.show()

s1_obj = S1()
Func(s1_obj)

s2_obj = S2()
Func(s2_obj)

4.类属性、实例属性

在前面的例子中我们接触到的就是实例属性(对象属性),顾名思义,类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本,这个和C++中类的静态成员变量有点类似。对于公有的类属性,在类外可以通过类对象和实例对象访问

类属性

class People(object):
    name = 'Tom'  #公有的类属性
    __age = 12     #私有的类属性

p = People()

print(p.name)           #正确
print(People.name)      #正确
print(p.__age)            #错误,不能在类外通过实例对象访问私有的类属性
print(People.__age)        #错误,不能在类外通过类对象访问私有的类属性

实例属性(对象属性)
class People(object):
    address = '山东' #类属性
    def __init__(self):
        self.name = 'xiaowang' #实例属性
        self.age = 20 #实例属性

p = People()
p.age =12 #实例属性
print(p.address) #正确
print(p.name)    #正确
print(p.age)     #正确

print(People.address) #正确
print(People.name)    #错误
print(People.age)     #错误

注:
如果需要在类外修改类属性,必须通过类对象去引用然后进行修改。如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。

class People(object):
    country = 'china' #类属性


print(People.country)
p = People()
print(p.country)
p.country = 'japan'
print(p.country)      #实例属性会屏蔽掉同名的类属性
print(People.country)
del p.country    #删除实例属性
print(p.country)

5.类方法和静态方法

类方法
是类对象所拥有的方法,需要用修饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数(当然可以用其他名称的变量作为其第一个参数,但是大部分人都习惯以’cls’作为第一个参数的名字,就最好用’cls’了),能够通过实例对象和类对象去访问。

class People(object):
    country = 'china'
    #类方法,用classmethod来进行修饰
    @classmethod
    def getCountry(cls):
        return cls.country

p = People()
print(p.getCountry())    #可以用过实例对象引用
print(People.getCountry())    #可以通过类对象引用

静态方法
需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数

class People(object):
    country = 'china'

    @staticmethod
    #静态方法
    def getCountry():
        return People.country


print(People.getCountry())

6.__new__方法

__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供
__new__必须要有返回值,返回实例化出来的实例,这点在自己实现
__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例

__init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值

我们可以将类比作制造商,__new__方法就是前期的原材料购买环节,__init__方法就是在有原材料的基础上,加工,初始化商品环节

class Dog(object):
    def __init__(self):
        print("----init方法-----")

    def __new__(cls):#cls此时是Dog指向的那个类对象

        #print(id(cls))
        print("----new方法-----")
        return object.__new__(cls)


#print(id(Dog))
a = Dog()

7.单例模式

确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,单例模式是一种对象创建型模式。

class Dog(object):

    __instance = None

    def __new__(cls):
        if cls.__instance == None:
            cls.__instance = object.__new__(cls)
            return cls.__instance
        else:
            #return 上一次创建的对象的引用
            return cls.__instance

a = Dog()
print(id(a))
b = Dog()
print(id(b))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值