1. 文章
  2. 文章详情

Python 面向对象OOP基础

面向对象OOP

  • 类(Class)
  • 对象(Object)
  • 实例(Instance)

类: 一个抽象的存在

实例: 是真实存在的类

对象: 是类的实例

对象: 包括了 类的属性行为, 还有实例所都有的具体表现形式

在面向对象的程序设计中, 首先要抽离出实体, 以及这个实体所拥有的属性和行为(方法).

面向对象的三大特点: 封装, 继承, 多态

封装

class Animal(object):
def __init__(self, args):
super(Animal, self).__init__()
self.__name = args.get("name")
self.age = args.get("age")

def call(self):
print("Animal(name:{0}, age:{1}) Call....".format(self.__name, self.age));

def setAnimalInfo(self, *, name, age):
self.__name = name
self.age = age

def getAnimalInfo(self):
return {"name": self.__name, "age": self.age}

def __str__(self): # 重写父类方法
return "Animal(name:{0}, age:{1})".format(self.__name, self.age)


pig = Animal({})
pig.setAnimalInfo(name="tom", age=2)
pig.call() # Animal(name:tom, age:2) Call....

pig.age = 3
print(pig.age) # 3
print(pig._Animal__name) # tom 不建议这样访问
# print(pig.__name) # AttributeError: 'Animal' object has no attribute '__name'
pig.__name = "jack" # 这么写是错误的, 虽然Python没有限制
print(pig.__name) # jack 实际上就是给 pig 绑了一个新的属性

pig.call() # Animal(name:tom, age:3) Call....

所谓封装, 就是将类的属性设为私有, 然后开放属性的get, set方法. 这样会提高程序的健壮性(比如set时, 验证实参是否合法)

因为构造方法(__init__(self, args))中, 存在必选参数, 所以在初始化实例时 pig = Animal({})

实际上私有属性, 在实例化对象时, 就已经改了变量名, 所以才有的 AttributeError: 'Animal' object has no attribute '__name' 的错误信息

pig.__name = "jack" 就像当于给pig实例, 重新绑定了新的属性(这样写虽然语法没有错, 但不建议这样写. 

继承

class Animal(object) Animal 继承自 object

class Dog(Animal):
def __init__(self, args):
super(Dog, self).__init__(args)

def call(self):
# print("Dog(name:{0}, age:{1}) wang....".format(super().__name, super.age));
print("Dog(name:{0}, age:{1}) wang....".format(super(Dog, self).getAnimalInfo().get("name"),
super(Dog, self).getAnimalInfo().get("age")));

def __str__(self): # 重写父类方法
# return "Dog(name:{0}, age:{1})".format(super().__name, super.age)
return "Dog(name:{0}, age:{1})".format(super(Dog, self).getAnimalInfo().get("name"),
super(Dog, self).getAnimalInfo().get("age"))


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

def call(self):
# print("Cat(name:{0}, age:{1}) miao....".format(self.__name, self.age));
print("Cat(name:{0}, age:{1}) miao....".format(super(Cat, self).getAnimalInfo().get("name"),
super(Cat, self).getAnimalInfo().get("age")));

def __str__(self): # 重写父类方法
# return "Cat(name:{0}, age:{1})".format(self.__name, self.age)
return "Cat(name:{0}, age:{1})".format(super(Cat, self).getAnimalInfo().get("name"),
super(Cat, self).getAnimalInfo().get("age"))


dog = Dog({"name": "lucy", "age": 2})
cat = Cat({"name":"lola", "age":1})

dog.call()
cat.call()

print("pig is Animal", isinstance(pig, Animal))
print("dog is Dog", isinstance(dog, Dog))
print("cat is Cat", isinstance(cat, Cat))
print("dog is Animal", isinstance(dog, Animal))
print("cat is Animal", isinstance(cat, Animal))
# Dog(name:lucy, age:2) wang....
# Cat(name:lola, age:1) miao....
# pig is Animal True
# dog is Dog True
# cat is Cat True
# dog is Animal True
# cat is Animal True

在子类中, 获取父类的引用 super(Dog, self). 而在子类中要想拿到父类的属性, 只能通过父类中提供的开放接口来实现了.

多态

从上面的程序中可以看出, Animal重写了他的父类的__str__方法, Cat和Dog也重写了这个方法. 有继承方法重写, 自然就有多态了.

def getAnimal(animal):
print(animal)

getAnimal(pig)
getAnimal(dog)
getAnimal(cat)
# Animal(name:tom, age:3)
# Dog(name:lucy, age:2)
# Cat(name:lola, age:1)

虽传入的都是 Animal类, 但执行的却有着不同的行为. 这就是多态

发表评论

登录后才能评论

评论列表(0条)