Python 多态与封装

什么是多态?

多态指的是在一个类中表现出多种状态,通过继承来实现的。

在java中的表现:在一个参数中需要给参数指定数据类型,如果这个地方可以接收两个以上类型的参数,那么这些类型应该有一个父类,这个父类是所有子类对象的类型。

多态的表现形式:

def func(Cat mao): pass
def func(Dog gou): pass
def func(Animal gou|mao): pass

在python中,函数的参数不需要指定数据类型,所以也不需要通过继承的形式来统一一组类的类型。换句话说,所有的对象其实都是object类型,所以在python当中其实处处是多态。即:

def func(a):   # 其中a既可以传猫也可以传狗类型,随便传任意类型。

鸭子类型:

def len(obj):
len() # str list tuple dict set range()
print()  # 所有的对象都是鸭子类型

不是明确的通过继承实现的多态,而实通过一个模糊的概念来判断这个函数能不能接收这个类型的参数。

封装

什么是封装?封装可以分为两种:狭义上的封装与广义上的封装

广义上的封装:

广义上的封装是将所写的代码用一个容器封装起来,表现形式为:

class 类名:
    def 方法1(self):pass

上面定义的类是为了只有在这个类的对象才能使用定义在类中放入方法。

狭义上的封装:

狭义上的封装: 主要是将一个名字藏在类中。

class Goods:
    __discount = 0  # 私有的静态变量
    print(__discount)
Goods()  # 在类内部,是可以打印出私有的静态变量
print(Goods.__discount)  # AttributeError: type object 'Goods' has no attribute '__discount'

从上面的例子可以看出,在类的内部是可以打印出私有的静态变量,而在类的外部是不能引用私有的静态变量

类中的静态变量和方法名在程序在加载的过程中就已经执行完了,不需要等待调用。

而在这个类加载完成之前,Goods这个名字还没有出现在内存空间中。

私有的静态属性可以在类的内部使用,用来隐藏某个变量的值.

查看隐藏在类内部静态变量存在的形式:

class Goods:
    __discount = 0
print(Goods.__dict__)    #  '_Goods__discount': 0

通过查找发现,在类内部私有的静态变量存在是以'_'单下划线形式,即:_Goods__discount.若在外部调用使用Goods._Goods__discount去输出会有什么效果,试试:

class Goods:
    __discount = 0
print(Goods._Goods__discount)    # 0

发现我们能输出私有静态变量.而在编程规范的角度上出发,我们不能在类的外部使用私有变量

上面我们也初步了解到了私有变量,那为什么我们要定义一个私有变量呢?

1 首先,是不希望用户看到私有变量;

2 其次,不希望用户随便修改私有变量;

3 再次,若可以修改时,希望用户在修改私有变量时有一些限制,目的是为了保护数据的安全;

4 最后,有些方法与属性不希望被子类调用

类中的私有成员分类

1 私有的静态属性       # 如类中属性:__discount = 0

2 私有的对象属性       #  如__init__中: self.__name

3 私有的方法              # 如类中定义的 def __func(self):

私有对象属性

1 class Student:
2     def __init__(self,name):
3         self.__name = name
4 colin = Student('科林')
5 print(colin.name)     # AttributeError: 'Student' object has no attribute 'name'
6 print(colin.__name)    # AttributeError: 'Student' object has no attribute '__name'
1 class Student:
2     def __init__(self,name):
3         self.__name = name
4 
5     def name(self):       # 通过调用类方法将类对象属性打印出来
6         return self.__name
7 colin = Student('科林')
8 print(colin.name())  # 科林

商品类打折例题:

 1 class Goods:
 2     __discount = 0.7  # 私有的静态属性
 3     def __init__(self,name,price):
 4         self.name = name
 5         self.__price = price   # 隐藏了商品的价格
 6     @property
 7     def price(self):
 8         return self.__price * Goods.__discount
 9 
10 apple = Goods('APPLE',5)
11 print(apple.price)       # 3.5

升级(修改类对象私有属性):

 1 class Goods:
 2     __discount = 0.7  # 私有的静态属性
 3     def __init__(self,name,price):
 4         self.name = name
 5         self.__price = price   # 隐藏了商品的价格
 6     @property
 7     def price(self):
 8         return self.__price * Goods.__discount
 9     def change_price(self,new_price):
10         if type(new_price) is int:
11             self.__price = new_price    # 修改对象属性
12         else:
13             print('本次价格修改不成功')
14 
15 apple = Goods('APPLE',5)
16 print(apple.price)       # 3.5
17 apple.change_price(10)
18 print(apple.price)       # 7
19 apple.change_price('dfred')
20 print(apple.price)

前面我们已经介绍过,当类私有属性在类的内部会发生变形,那类私有变量能不能被继承呢?先举一个例子:

1 class A:
2     __country = 'China'
3     print(__country)
4 print(A.__dict__)       # 其中: 类私有属性在显示以:_A__country方式储存
5 A.__language = 'Chinese'  # __language': 'Chinese'
6 print(A.__dict__)
7 print(A.__language)
1 class A:
2     __country = 'China'
3 
4 class B(A):
5     print(__country)   # NameError: name '_B__country' is not defined
1 class A:
2     __country = 'China'
3 
4 class B(A):
5     print(A._A__country)    # China

装饰器(property)

property在python中是一个装饰器函数,而所有的装饰器函数都怎么使用?

在函数,方法,类的上面一行直接用@+装饰器的名字

装饰器的分类:可以分为三种:1. 装饰函数 2. 装饰方法(property) 3. 装饰类

装饰器方法:

1 # 例1:
2 class Student:
3     def __init__(self,name):
4         self.__name = name
5     @property
6     def name(self):       # 通过调用类方法将类对象属性打印出来
7         return self.__name
8 colin = Student('科林')
9 print(colin.name)  # 科林
 1 # 例2:
 2 from math import pi
 3 class Circle:
 4     def __init__(self,r):
 5         self.r = r
 6     @property
 7     def area(self):
 8         return self.r ** 2 * pi
 9     @property
10     def perimeter(self):
11         return 2 * self.r * pi
12 c1 = Circle(10)
13 print(c1.area)      # 314.1592653589793
14 print(c1.perimeter)  # 62.83185307179586
原文地址:https://www.cnblogs.com/colin1314/p/9555545.html