重载和重写,这是两个新概念,是两个令我们容易混淆的概念。方法重载(overloading method)
成都创新互联公司专注于企业成都全网营销推广、网站重做改版、市中网站定制设计、自适应品牌网站建设、HTML5、商城网站建设、集团公司官网建设、外贸网站建设、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为市中等各大城市提供网站开发制作服务。
是在一个类里面,方法名字相同,而参数不同。返回类型呢?可以相同也可以不同。方法重写(overiding method)
子类不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖。方法重载是让类以统一的方式处理不同类型数据的
一种手段。Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义。调用方法时通过传递给它们的不同个数和
类型的参数来决定具体使用哪个方法,
这就是多态性。方法重写:在Java中,子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定
的修改,这就需要采用方法的重写。方法重写又称方法覆盖。
若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。
如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类重写方法的规则:
参数列表必须完全与被重写的方法的相同,否则不能称其为重写而是重载.
返回的类型必须一直与被重写的方法的返回类型相同,否则不能称其为重写而是重载.访问修饰符的限制一定要大于被重写方法的访问修饰符
(publicprotecteddefaultprivate)重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽
泛的检查型异常.例如,父类的一个方法申明了一个检查异常IOException,在重写这个方法是就不能抛出Exception,只能抛出
IOException的子类异常,可以抛出非检查异常.重载的规则:必须具有不同的参数列表;可以有不同的返回类型,只要参数列表不同就可以
了;可以有不同的访问修饰符;可以抛出不同的异常;注意,Java的方法重载要求同名的方法必须有不同的参数表,仅有返回类型不同是不足以区分两
个重载的方法。重写方法只能存在于具有继承关系中,重写方法只能重写父类非私有的方法。下面分别举一个例子来说明方法重载:public class
TestOverLoad{ public static void main(String[] args) {Test test = new
Test(); test.print(null); } }class Test{ public void print(String
some){System.out.println("String version print"); } public void
print(Object some){ System.out.println("Object version print");
}}该程序输出的结果是String version print。
第一点:封装
隐藏对象的属性和实现细节,仅对外提供公共访问方式,在Python中用双下线开头的方式将属性设置成私有的。
拥有三个好处:将变化隔离,便于使用,提高复用性,提高安全性。
第二点:继承
继承是一种创建新类的方式,在Python中,新建的类可以继承一个或多个父类,父类又被称为基类或超类,新建的类称为派生类或子类。即一个派生类继承基类的字段和方法,继承也允许把一个派生类的对象作为一个基类对象对待。
第三点:多态
一种事物的多种体现形式,函数的重写其实就是多态的一种体现。Python中,多态指是父类的引用指向子类的对象。
实现多态的步骤:
1. 定义新的子类;
2. 重写对应的父类方法;
3. 使用子类的方法直接处理,不调用父类的方法;
多态的好处:
1. 增加了程序的灵活性;
2. 增加了程序的可扩展性。
1、更换anaconda源,使用清华大学镜像:清华大学镜像。
2、更换pip源,在python安装目录的bin目录下运行。
3、设置pip镜像源环境,保存即配置好了pip镜像源,即可完成重写。
魔法方法 (Magic Methods) 是Python中的内置函数,一般以双下划线开头和结尾,例如__ init__ 、 __del__ 等。之所以称之为魔法方法,是因为这些方法会在进行特定的操作时会自动被调用。
在Python中,可以通过dir()方法来查看某个对象的所有方法和属性,其中双下划线开头和结尾的就是该对象的魔法方法。以字符串对象为例:
可以看到字符串对象有 __add__ 方法,所以在Python中可以直接对字符串对象使用"+"操作,当Python识别到"+"操作时,就会调用该对象的 __add__ 方法。有需要时我们可以在自己的类中重写 __add__ 方法来完成自己想要的效果。
我们重写了 __add__ 方法,当Python识别"+"操作时,会自动调用重写后的 __add__ 方法。可以看到,魔法方法在类或对象的某些事件出发后会自动执行,如果希望根据自己的程序定制特殊功能的类,那么就需要对这些方法进行重写。使用魔法方法,我们可以非常方便地给类添加特殊的功能。
1、构造与初始化
__ new __ 、 __ init __ 这两个魔法方法常用于对类的初始化操作。上面我们创建a1 = A("hello")时,但首先调用的是 __ new __ ;初始化一个类分为两步:
a.调用该类的new方法,返回该类的实例对象
b.调用该类的init方法,对实例对象进行初始化。
__new__ (cls, *args, **kwargs)至少需要一个cls参数,代表传入的类。后面两个参数传递给 __ init __ 。在 __ new __ 可以决定是否继续调用 __ init __ 方法,只有当 __ new __ 返回了当前类cls的实例,才会接着调用 __ init __ 。结合 __ new __ 方法的特性,我们可以通过重写 __ new __ 方法实现Python的单例模式:
可以看到虽然创建了两个对象,但两个对象的地址相同。
2、控制属性访问这类魔法
方法主要对对象的属性进行访问、定义、修改时起作用。主要有:
__getattr__(self, name): 定义当用户试图获取一个属性时的行为。
__getattribute__(self, name):定义当该类的属性被访问时的行为(先调用该方法,查看是否存在该属性,若不存在,接着去调用getattr)。
__setattr__(self, name, value):定义当一个属性被设置时的行为。
当初始化属性时如self.a=a时或修改实例属性如ins.a=1时本质时调用魔法方法self. __ setattr __ (name,values);当实例访问某个属性如ins.a本质是调用魔法方法a. __ getattr __ (name)
3、容器类操作
有一些方法可以让我们自己定义自己的容器,就像Python内置的List,Tuple,Dict等等;容器分为可变容器和不可变容器。
如果自定义一个不可变容器的话,只能定义__ len__ 和__ getitem__ ;定义一个可变容器除了不可变容器的所有魔法方法,还需要定义__ setitem__ 和__ delitem__ ;如果容器可迭代。还需要定义__ iter __。
__len__(self):返回容器的长度
__getitem__(self,key):当需要执行self[key]的方式去调用容器中的对象,调用的是该方法
__setitem__(self,key,value):当需要执行self[key] = value时,调用的是该方法
__iter__(self):当容器可以执行 for x in container:,或者使用iter(container)时,需要定义该方法
下面举一个例子,实现一个容器,该容器有List的一般功能,同时增加一些其它功能如访问第一个元素,最后一个元素,记录每个元素被访问的次数等。
这类方法的使用场景主要在你需要定义一个满足需求的容器类数据结构时会用到,比如可以尝试自定义实现树结构、链表等数据结构(在collections中均已有),或者项目中需要定制的一些容器类型。
魔法方法在Python代码中能够简化代码,提高代码可读性,在常见的Python第三方库中可以看到很多对于魔法方法的运用。
因此当前这篇文章仅是抛砖引玉,真正的使用需要在开源的优秀源码中以及自身的工程实践中不断加深理解并合适应用。
class Set(object):
def __init__(self,data=None):
if data == None:
self.__data = []
else:
if not hasattr(data,'__iter__'):
#提供的数据不可以迭代,实例化失败
raise Exception('必须提供可迭代的数据类型')
temp = []
for item in data:
#集合中的元素必须是可哈希
hash(item)
if not item in temp:
temp.append(item)
self.__data = temp
#析构函数
def __del__(self):
del self.__data
#添加元素,要求元素必须可哈希
def add(self, other):
hash(other)
if other not in self.__data:
self.__data.append(other)
else:
print('元素已存在,操作被忽略')
#删除元素
def remove(self,other):
if other in self.__data:
self.__data.remove(other)
print('删除成功')
else:
print('元素不存在,删除操作被忽略')
#随机弹出并返回一个元素
def pop(self):
if not self.__dat:
print('集合已空,弹出操作被忽略')
return
import random
item = random.choice(self.__data)
self.__data.remove(item)
return item
#运算符重载,集合差集运算
def __sub__(self, other):
if not isinstance(other,Set):
raise Exception('类型错误')
#空集合
result = Set()
#如果一个元素属于当前集合而不属于另一个集合,添加
for item in self.__data:
if item not in other.__data:
result.__data.append(item)
return result
#提供方法,集合差集运算,复用上面的代码
def difference(self,other):
return self - other
#|运算符重载,集合并集运算
def __or__(self, other):
if not isinstance(other,Set):
raise Exception('类型错误')
result = Set(self.__data)
for item in other.__data:
if item not in result.__data:
result.__data.append(item)
return result
#提供方法,集合并集运算
def union(self,otherSet):
return self | otherSet
#运算符重载,集合交集运算
def __and__(self, other):
if not isinstance(other,Set):
raise Exception('类型错误')
result = Set()
for item in self.__data:
if item in other.__data:
result.__data.append(item)
return result
#^运算符重载,集合对称差集
def __xor__(self, other):
return (self-other) | (other-self)
#提供方法,集合对称差集运算
def symetric_difference(self,other):
return self ^ other
#==运算符重载,判断两个集合是否相等
def __eq__(self, other):
if not isinstance(other,Set):
raise Exception('类型错误')
if sorted(self.__data) == sorted(other.__data):
return True
return False
#运算符重载,集合包含关系
def __gt__(self, other):
if not isinstance(other,Set):
raise Exception('类型错误')
if self != other:
flag1 = True
for item in self.__data:
if item not in other.__data:
#当前集合中有的元素不属于另一个集合
flag1 = False
break
flag2 = True
for item in other.__data:
if item not in self.__data:
#另一集合中的元素不属于当前集合
flag2 = False
break
if not flag1 and flag2:
return True
return False
#=运算符重载,集合包含关系
def __ge__(self, other):
if not isinstance(other,Set):
raise Exception('类型错误')
return self == other or self other
#提供方法,判断当前集合是否为另一个集合的真子集
def issubset(self,other):
return selfother
#提供方法,判断当前集合是否为另一集合的超集
def issuperset(self,other):
return self other
#提供方法,清空集合所有元素
def clear(self):
while self.__data:
del self.__data[-1]
print('集合已清空')
#运算符重载,使得集合可迭代
def __iter__(self):
return iter(self.__data)
#运算符重载,支持in运算符
def __contains__(self, item):
return item in self.__data
#支持内置函数len()
def __len__(self):
return len(self.__data)
#直接查看该类对象时调用该函数
def __repr__(self):
return '{'+str(self.__data)[1:-1]+'}'
#使用print()函数输出该类对象时调用该函数
__str__ = __repr__
从父类继承中的方法,如果不满足程序的需求,就需要重写。
方法重写指的是在子类中自定义实现父类中的同名方法。