python的类解析,继承、重构及多态详解

1,332 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

python创建类

1.创建类

如下定义一个动物类Animal为基类,它基本两个实例属性name和age、一个方法call。

 class people:
     #定义基本属性
     name = ''
     age = 0
     #定义私有属性,私有属性在类外部无法直接进行访问
     __weight = 0
     #定义构造方法
     def __init__(self,n,a,w):
         self.name = n
         self.age = a
         self.__weight = w
     def speak(self):
         print("%s 说: 我 %d 岁。" %(self.name,self.age))
  
 # 实例化类
 p = people('runoob',10,30)
 p.speak()

2.继承

 class Animal(object):  #  python3中所有类都可以继承于object基类
    def __init__(self, name, age):
        self.name = name
        self.age = age
 ​
    def call(self):
        print(self.name, '会叫')
 ​
 ######
 # 现在我们需要定义一个Cat 猫类继承于Animal,猫类比动物类多一个sex属性。 
 ######
 class Cat(Animal):
    def __init__(self,name,age,sex):
        super(Cat, self).__init__(name,age)  # 不要忘记从Animal类引入属性
        self.sex=sex
 ​
 if __name__ == '__main__':  # 单模块被引用时下面代码不会受影响,用于调试
    c = Cat('喵喵', 2, '男')  #  Cat继承了父类Animal的属性
    c.call()  # 输出 喵喵 会叫 ,Cat继承了父类Animal的方法 

注意:注意: 一定要用 super(Cat, self).init(name,age) 去初始化父类,否则,继承自 Animal的 Cat子类将没有 name和age两个属性。 函数super(Cat, self)将返回当前类继承的父类,即 Animal,然后调用init()方法,注意self参数已在super()中传入,在init()中将隐式传递,不能再写出self。

3.重构

 class Cat(Animal):
    def __init__(self, name, age, sex):
        super(Cat, self).__init__(name,age)
        self.sex = sex
 ​
    def call(self):
        print(self.name,'会“喵喵”叫')
 ​
 if __name__ == '__main__':
    c = Cat('喵喵', 2, '男')
    c.call()  # 输出:喵喵 会“喵喵”叫

注意:类方法的调用顺序,当我们在子类中重构父类的方法后,Cat子类的实例先会在自己的类 Cat 中查找该方法,当找不到该方法时才会去父类 Animal 中查找对应的方法。

4.Python中子类与父类的关系

 class Animal(object):
    pass
 ​
 class Cat(Animal):
    pass
 ​
 A= Animal()
 C = Cat()

子类与父类的关系是 “is” 的关系,如上 Cat 继承于 Animal 类,我们可以说:

“A”是 Animal 类的实例,但,“A”不是 Cat 类的实例。

“C”是 Animal 类的实例,“C”也是 Cat 类的实例。

判断对象之间的关系,我们可以通过 isinstance (变量,类型) 来进行判断:

 print('"A" IS Animal?', isinstance(A, Animal))
 print('"A" IS Cat?', isinstance(A, Cat))
 print('"C" IS Animal?', isinstance(C, Animal))
 print('"C" IS Cat?', isinstance(C, Cat))

输出结果:

 "A" IS Animal? True
 "A" IS Cat? False
 "C" IS Animal? True
 "C" IS Cat? True

拓展: isinstance() 判断变量类型

函数 isinstance() 不止可以用在我们自定义的类,也可以判断一个变量的类型,如判断数据类型是否为 int、str、list、dict 等。

 print(isinstance(100, int))
 print(isinstance('100', int))
 print(isinstance(100, str))
 print(isinstance('100', str))

输出:

 True
 False
 False
 True

5.python 中多态

类具有继承关系,并且子类类型可以向上转型看做父类类型,如果我们从 Animal 派生出 Cat和 Dog,并都写了一个 call() 方法,如下示例:

class Animal(object):  
   def __init__(self, name, age):
       self.name = name
       self.age = age
   def call(self):
       print(self.name, '会叫')

class Cat(Animal):
   def __init__(self, name, age, sex):
       super(Cat, self).__init__(name, age)
       self.sex = sex

   def call(self):
       print(self.name, '会“喵喵”叫')

class Dog(Animal):
   def __init__(self, name, age, sex):
       super(Dog, self).__init__(name, age)
       self.sex = sex
   def call(self):
       print(self.name, '会“汪汪”叫')

我们定义一个 do 函数,接收一个变量 ‘all’,如下:

def do(all):
   all.call()

A = Animal('小黑',4)
C = Cat('喵喵', 2, '男')
D = Dog('旺财', 5, '女')

for x in (A,C,D):
   do(x)

输出结果:

小黑 会叫
喵喵 会“喵喵”叫
旺财 会“汪汪”叫

小知识:多态

这种行为称为多态。也就是说,方法调用将作用在 all 的实际类型上。C 是 Cat 类型,它实际上拥有自己的 call() 方法以及从 Animal 继承的 call 方法,但调用 C .call() 总是先查找它自身的定义,如果没有定义,则顺着继承链向上查找,直到在某个父类中找到为止。

传递给函数 do(all) 的参数 all 不一定是 Animal 或 Animal 的子类型。任何数据类型的实例都可以,只要它有一个 call() 的方法即可。其他类不继承于 Animal,具备 call 方法也可以使用 do 函数。这就是动态语言,动态语言调用实例方法,不检查类型,只要方法存在,参数正确,就可以调用。

python批量建立对象

方法一:

class Blog:
   def __init__(self,num):
       print("a new object num is",num)
       self.value = num
     
   def __str__(self):
       return str(self.value+3)
 
# 循环建立四个对象,locals()函数可以将字符串转换为变量名!
#具体的操作和含义我并不清楚,大家可以自行百度~
for i in range(1,5):
    locals()['blog_'+str(i)] = Blog(i)
 
#验证是否有blo_3这个对象变量
print(blog_3)
 

效果:

('a new object num is', 1)
('a new object num is', 2)
('a new object num is', 3)
('a new object num is', 4)
3

方法二:


class bianyuan(custom):
    cj = 430080
    def __init__(self, name, data, cj):
        super(bianyuan, self).__init__(name)
        self.cj = cj
        self.data = data
    def distribute(self, slip):
        self.data = self.data + slip


flag = 1  ##设置flag,用于批量命名对象
for name in m_qos_suit_keys:
    # for i in range(1,101):
    if flag<101:
        locals()["bianyuan_"+str(flag)] = bianyuan(name, 0, m_limit.get(name))  ##批量命名对象
        flag += 1
        
bianyuan_1.distribute(slip)
bianyuan_2.distribute(slip)
bianyuan_3.distribute(slip)

print(bianyuan_1.data)
print(bianyuan_1.name)
print(bianyuan_2.data)
print(bianyuan_2.name)

\