天天看点

python面向对象的特点_Python面向对象基本特征

面向对象基本特征

封装

封装是指对外界隐藏信息,不能随意访问、修改对象的数据和方法

封装是通过限制类的属性和方法的访问方式来实现的封装效果

封装的三个层次:

类的封装:外部可以任意访问、修改类中的属性和方法

私有属性:外部不可以访问、修改勒种的属性和方法

公有方法+私有属性:外部有条件限制的访问、修改属性,调用方法

封装表现1:

类的定义:将某些特定属性和方法进行“隔离”

每个学生有自己的年龄,外部可以任意读取或者修改

class Student:

def __init__(self,name,age):

self.name = name

self.age = age

s1 = Student("李白",18)

s2 = Student("杜甫",20)

s2.age = 200

print(s1.name)

print(s2.age)

封装表现2:

属性私有:只能在类的内部使用,外部不能使用

不让外部读取、修改学生的年龄

class Student:

def __init__(self,name,age):

self.name = name

self.__age = age#使用两个下划线开头的属性,定义为私有属性

print(self.__age)

__secret = True

s1 = Student("李白",18)

# print(s1.__age)#外界无法直接通过属性名称来访问

#虽然语法可以在外部通过_Student__age访问到私有属性,但是不推荐使用

print(s1._Student__age)

#__dict__查看当前对象或者类有哪些属性

print(s1.__dict__)

print(Student.__dict__)

封装表现3:

私有属性+ 公有方法:有限制条件的开放给外部

可以读取年龄,但不能随意修改年龄

设定年龄必须在(1,125)之间

class Student:

def __init__(self,name,age):

self.name = name

self.__age = age

def getAge(self):

return self.__age

def setAge(self,age):

if 0 < age < 125:

self.__age = age

else:

print("年龄不符合人类")

s1 = Student("李白",18)

print(s1.getAge())

s1.setAge(200)

print(s1.getAge())

私有方法

可以在类的内部使用,有条件的开放给外部

class Person:

def __tellSercert__(self):

print("夏天夏天悄悄过去,留下小秘密~~~~")

def talk(self,object):

if object == "好基友":

self.__tellSercert__()

else:

print("我是一个木得感情木得秘密的人")

ming = Person()

ming.talk("好基友")

ming.talk("隔壁小黑")

封装的简化写法

装饰器

property装饰器:把一个方法伪装成一个属性,在调用这个方法的时候不需要加()就可以直接得到返回值

class Dog:

@property#装饰器

def bark(self):

print("旺旺旺~~~")

return 89757

d = Dog()

num = d.bark #注意这里没有括号呦

print(num)

总结

使用@property装饰器时,方法名不必与属性名相同

可以更好的防止外部通过猜测私有属性名称来访问

凡是赋值语句就会触发set方法,获取属性值会触发get方法

继承

面临的问题:

相似类型的定义会产生大量重复的代码

类的定义没有很好的扩展性‘

解决的方法:

定义类和类之间的关系,子类拥有父类的全部属性和方法,并可以为之扩充

示例

class Pet:

def __init__(self,name,age):

self.name = name

self.age = age

print(f"一只名字叫{self.name}的宠物出生了")

def eat(self):

print(f"{self.name}在吃东西~~~")

def run(self):

print(f"{self.name}在溜达~~~")

class Dog(Pet):

pass

class Cat(Pet):

pass

d = Dog("咯咯",3)

d.run()

c = Cat("布丁",1)

c.eat()

1.继承的概念:

Dog和Cat继承了Pet类

Dog和Cat称为Pet的子类、派生类

Pet称为Dog和Cat的父类、超类、基类

子类默认拥有父类公有的属性和方法的定义

2.子类调用方法的顺序

调用方法时,子类中有的,调用子类中的

子类中没有的,调用父类的

一旦在子类中找到,就不在去父类中查找了

子类不能继承父类的私有属性或者方法

class Father:

__secret = "小秘密"

story = "从前有座山,山上有座庙"

def tellStory(self):

print(self.story)

def __tellSecret(self):

print(self.__secret)

class Son(Father):

def tell(self):

# self.tellStory()

self.__tellSecret()

s = Son()

s.tell()

3.重写/覆盖

子类和父类拥有相同名称的方法

可以理解为子类对于父类行为的扩展和补充

class Pet:

master = True

def __init__(self,name,age):

self.name = name

self.age = age

print(f"一只名字叫{self.name}的宠物出生了")

def eat(self):

print(f"{self.name}在吃东西~~~")

def run(self):

print(f"{self.name}在溜达~~~")

class Dog(Pet):

#重写父类方法

def eat(self):

print(f"{self.name}在啃骨头")

#扩充,定义子类特有功能

def lookAfter(self):

print(f"{self.name}在看门,汪汪汪!")

d = Dog("旺财",2)

d.eat()

d.lookAfter()

4.子类可以在类定义时,可以使用super()调用父类的方法

应用1:和重写不同,重写是对父类方法的完全覆盖,这是对父类方法的补充

class Pet:

def __init__(self,name,age):

self.name = name

self.age = age

print(f"一只名字叫{self.name}的宠物出生了")

def eat(self):

print(f"{self.name}在吃东西~~~")

def run(self):

print(f"{self.name}在溜达~~~")

class Cat(Pet):

def eat(self):

print(f"{self.name}伸了个懒腰")

super().eat()

print(f"{self.name}吃完东西后,舔了舔爪子")

c = Cat("布丁",2)

c.eat()

应用2:对象初始化时,简化重复属性的赋值

class Cat(Pet):

def __init__(self,name,age,sex):

# self.name = name

# print(f"一只名叫{self.name}的宠物出生了")

super().__init__(name)#代替了上两句代码,简化了重复属性的赋值

self.age = age

self.sex = sex

5.多继承

子类可以有多个父类

例如:狗是脊椎动物,哺乳动物,宠物。。。

class Father:

caihua = "有才"

class Mother:

yanzhi = "有貌"

class Child(Father,Mother):

pass

c = Child()

print(c.caihua,c.yanzhi)

print(Child.__bases__)#可以通过类名.__bases__查看其父类

6.访问子类的属性或者方法时,解析的路径(顺序)

class Father:

def getMoney(self):

print("爸爸给了零花钱")

class Mother:

def getMoney(self):

print("妈妈给了零花钱")

class Child(Father,Mother):

def getMoney(self):

super().getMoney()

#按照继承的顺序查找父类中的方法,所以先找Father类

print("孩子获得了零花钱")

c = Child()

c.getMoney()

从第一个父类开始向上查找,直到查找结束都没有,再对第二个父类进行查找

深度优先:Child -> Father -> GrandFather -> Mother

class GrandFather:

pass

# def getMoney(self):

# print("爷爷给了零花钱")

class Father(GrandFather):

pass

# def getMoney(self):

# print("爸爸给了零花钱")

class Mother:

def getMoney(self):

print("妈妈给了零花钱")

class Child(Father,Mother):

def getMoney(self):

super().getMoney()

#按照继承的顺序查找父类中的方法,所以先找Father类

print("孩子获得了零花钱")

c = Child()

c.getMoney()

print(Child.mro())#可以通过类名.mro()的方式来查看类的解析顺序

object是所有类的父类

“万事万物”皆为对象,因为所有的类都默认继承object

7.菱形继承

python面向对象的特点_Python面向对象基本特征

广度优先:Child -> Father -> Mother -> Human

python面向对象的特点_Python面向对象基本特征

多态

想要解决的问题

让程序能够有更强的灵活性

让程序能够有更好的适应性

概念:一个类的多种形态

情况1:通过继承和重写来实现

class Animal:

def eating(self):

print("动物在吃东西")

class Pet(Animal):

def eating(self):

print("宠物在吃东西")

class Dog(Pet):

def eating(self):

print("狗在啃骨头~")

class Cat(Pet):

def eating(self):

print("小猫在吃鱼")

class Zoo:

def animalEating(self,animal):

animal.eating()

z = Zoo()

a = Animal()

p = Pet()

d = Dog()

c = Cat()

#Dog和Cat都作为Animal的不同形态

#都可以直接调用animal所具有的属性和方法

z.animalEating(a)

z.animalEating(p)

z.animalEating(d)

z.animalEating(c)

情况2:Python持有

没有继承关系,但是也具备相同的特征、方法,也可以直接使用

class venusFlytrap:#捕蝇草

def eating(self):

print("捕蝇草在吃小虫子")

v = venusFlytrap()

z.animalEating(v)

捕蝇草不继承于Animal类,但是具有和它相同的特征,在python只要具有相同的特征和方法,没有继承关系也可以直接使用

type和isinstance

#type判断类型时,只看直接类型

print(type(c) is Cat)#True

print(type(c) is Animal)#False

print(type(c) is Pet)#False

#isinstance 判断对象是否为一个类型的实例

#判断实例类型时,涵盖父类的类型

print(isinstance(c,Cat))#True

print(isinstance(c,Pet))#True

print(isinstance(c,Animal))#True

print(isinstance(venusFlytrap,Animal))#False