1.私有属性和私有方法
私有属性 就是对象不希望公开的属性
私有方法 就是对象不希望公开的方法
在定义私有属性或方法时,在属性名或者方法名前增加两个下划线。
class Women:
def __init__(self, name):
self.name = name
self.__age = 18 # 私有属性
def secret(self):
print("%s的年龄是%d" % (self.name, self.__age))
def __secret(self): # 私有方法
print("%s今年%d了" % (self.name, self.__age))
xiaomei = Women("xiaomei")
# print(xiaomei.__age) # 私有属性,在外界不能够被直接访问,会报错
xiaomei.secret() # 但在对象的方法内部,是可以访问该对象的私有属性的
# xiaomei.__secret() # 私有方法,同样不允许在外界直接访问
2.继承
面向对象的三大特性:
封装:根据职责将属性和方法封装到一个抽象的类中。
继承:实现代码的重用,相同的代码不需要重复的编写。
多态:不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活性。
2.1 单继承 (子类只有一个父类)
(1)继承的概念、语法和特点
概念:子类拥有父类的所有方法和属性。
语法:在子类名后面加(父类名),子类可以直接享受父类中已经封装好的方法。
特点:传递性。子类拥有父类以及父类的父类中封装的所有的属性和方法。
class 类名(父类名):
pass
例子:
动物:吃喝跑睡;狗:吃喝跑睡叫;孝天川:吃喝跑睡叫飞
class Animal:
def eat(self):
print("吃")
def drink(self):
print("喝")
def run(self):
print("跑")
def sleep(self):
print("睡")
class Dog(Animal): # 继承自Animal类
def bark(self):
print("汪汪叫")
class XiaoTianQuan(Dog): # 继承自Dog类
def fly(self):
print("飞")
xiaohei = XiaoTianQuan()
xiaohei.eat()
xiaohei.drink()
xiaohei.run()
xiaohei.sleep()
xiaohei.bark()
xiaohei.fly()
专业术语: Dog类是Animal类的子类(派生类),Animal类是Dog类的父类(基类),Dog类从Animal类继承(派生)
(2)方法的重写
i) 覆盖父类的方法
狗会叫,但是哮天犬的叫声和普通狗不一样。
当父类封装的方法不能满足子类的需求时,可以对方法进行重写,即在子类中重新编写一下该方法。方法必须同名。
class Animal:
def eat(self):
print("吃")
class Dog(Animal):
def bark(self):
print("汪汪叫")
class XiaoTianQuan(Dog):
def fly(self):
print("飞")
def bark(self): # 同名方法重写
print("神狗在叫")
xiaohei = XiaoTianQuan()
xiaohei.eat()
xiaohei.bark() # 如果在子类中重写了父类的方法,那么会调用子类中重写的方法
xiaohei.fly()
输出:
吃
神狗在叫
飞
ii) 对父类方法进行扩展
在开发中,子类的方法实现中包含父类的方法实现,就可以使用扩展的方式。
① 在子类中重写父类方法,即定义一个相同名称的方法。
② super(). 调用父类中封装的方法。
③ 编写子类特有的代码
class Animal:
def eat(self):
print("吃")
class Dog(Animal):
def bark(self):
print("汪汪叫")
class XiaoTianQuan(Dog):
def fly(self):
print("飞")
def bark(self):
print("神一样的叫唤...")
super().bark() # 使用super(). 调用原本在父类中封装的方法
print("hahahahahahahah") # 针对子类特有的需求,编写代码
xiaohei = XiaoTianQuan()
xiaohei.bark() # 如果在子类中重写了父类的方法,那么会调用子类中重写的方法
输出:
神一样的叫唤...
汪汪叫
hahahahahahahah
(3)父类的私有属性和私有方法
i) 子类对象不能在自己的方法内部,直接访问父类的私有属性或私有方法。但是可以访问父类的公有属性和公有方法。
class A:
def __init__(self):
self.num1 = 100 # 公有属性
self.__num2 = 200 # 私有属性
def __test(self):
print("私有方法 %d %d" % (self.num1, self.__num2))
class B(A):
def demo(self):
# print("访问父类的私有属性 %d" % self.__num2) # 子类中的方法不能访问父类的私有属性
# self.__test() # 子类中的方法不能调用父类的私有方法
pass
b = B()
b.demo()
# print(b.__num2) # 在外界不能直接访问对象的私有属性/调用私有方法
# b.__test
ii) 子类对象可以通过父类的 公有方法 间接地访问私有属性或私有方法。
class A:
def __init__(self):
self.num1 = 100 # 公有属性
self.__num2 = 200 # 私有属性
def __test(self):
print("私有方法 %d %d" % (self.num1, self.__num2))
def test(self):
print("公有方法 %d %d" % (self.num1, self.__num2)) # 该类中的方法可以访问该类的私有属性
self.__test() # 该类的方法可以调用该类的私有方法
class B(A):
def demo(self):
print(self.num1) # 子类可以访问父类的公有属性
self.test() # 子类可以调用父类的公有方法
b = B()
b.demo()
2.2 多继承(子类有多个父类)
(1)概念、语法和注意事项
概念:子类具有所有父类的属性和方法。
语法:
class A:
def test(self):
print("test方法")
class B:
def demo(self):
print("demo方法")
class C(A, B): # 多继承的格式
pass
c = C()
c.test()
c.demo()
注意事项:
如果父类之间存在同名的属性或者方法,应该尽量避免使用多继承。
科普:
(1) Python中的MRO–方法搜索顺序:如果找到,就直接执行,不在搜索。
(2)object是Python为所有对象提供的基类,提供一些内置的方法和属性。
新式类:以object为基类的类,推荐
旧式类:不以object为基类的类,不推荐
Python3 中定义的类,如果没有指定父类,均默认以object作为基类。
Python2 中定义的类,如果没有指定父类,均为旧式类。
class A(object):
pass