python重写类
① python类的继承和多态代码详解
Python类的继承和多态代码详解
Python类的继承
在OOP(ObjectOrientedProgramming)程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Baseclass、Superclass)。
我们先来定义一个classPerson,表示人,定义属性变量name及sex(姓名和性别);
定义一个方法print_title():当sex是male时,printman;当sex是female时,printwoman。参考如下代码:
class Person(object):
def __init__(self,name,sex):
self.name = name
self.sex = sex
def print_title(self):
if self.sex == "male":
print("man")
elif self.sex == "female":
print("woman")
class Child(Person): # Child 继承 Person
pass
May = Child("May","female")
Peter = Person("Peter","male")
print(May.name,May.sex,Peter.name,Peter.sex) # 子类继承父类方法及属性
May.print_title()
Peter.print_title()
而我们编写Child类,完全可以继承Person类(Child就是Person);使用classsubclass_name(baseclass_name)来表示继承;
继承有什么好处?最大的好处是子类获得了父类的全部属性及功能。如下Child类就可以直接使用父类的print_title()方法
实例化Child的时候,子类继承了父类的构造函数,就需要提供父类Person要求的两个属性变量name及sex:
在继承关系中,如果一个实例的数据类型是某个子类,那它也可以被看做是父类(May既是Child又是Person)。但是,反过来就不行(Peter仅是Person,而不是Child)。
继承还可以一级一级地继承下来,就好比从爷爷到爸爸、再到儿子这样的关系。而任何类,最终都可以追溯到根类object,这些继承关系看上去就像一颗倒着的树。比如如下的继承树:
isinstance()及issubclass()
Python与其他语言不同点在于,当我们定义一个class的时候,我们实际上就定义了一种数据类型。我们定义的数据类型和Python自带的数据类型,比如str、list、dict没什么两样。
Python有两个判断继承的函数:isinstance()用于检查实例类型;issubclass()用于检查类继承。参见下方示例:
class Person(object):
pass
class Child(Person): # Child 继承 Person
pass
May = Child()
Peter = Person()
print(isinstance(May,Child)) # True
print(isinstance(May,Person)) # True
print(isinstance(Peter,Child)) # False
print(isinstance(Peter,Person)) # True
print(issubclass(Child,Person)) # True
Python类的多态
在说明多态是什么之前,我们在Child类中重写print_title()方法:若为male,printboy;若为female,printgirl
class Person(object):
def __init__(self,name,sex):
self.name = name
self.sex = sex
def print_title(self):
if self.sex == "male":
print("man")
elif self.sex == "female":
print("woman")
class Child(Person): # Child 继承 Person
def print_title(self):
if self.sex == "male":
print("boy")
elif self.sex == "female":
print("girl")
May = Child("May","female")
Peter = Person("Peter","male")
print(May.name,May.sex,Peter.name,Peter.sex)
May.print_title()
Peter.print_title()
当子类和父类都存在相同的print_title()方法时,子类的print_title()覆盖了父类的print_title(),在代码运行时,会调用子类的print_title()
这样,我们就获得了继承的另一个好处:多态。
多态的好处就是,当我们需要传入更多的子类,例如新增Teenagers、Grownups等时,我们只需要继承Person类型就可以了,而print_title()方法既可以直不重写(即使用Person的),也可以重写一个特有的。这就是多态的意思。调用方只管调用,不管细节,而当我们新增一种Person的子类时,只要确保新方法编写正确,而不用管原来的代码。这就是着名的“开闭”原则:
对扩展开放(Openforextension):允许子类重写方法函数
对修改封闭(Closedformodification):不重写,直接继承父类方法函数
子类重写构造函数
子类可以没有构造函数,表示同父类构造一致;子类也可重写构造函数;现在,我们需要在子类Child中新增两个属性变量:mother和father,我们可以构造如下(建议子类调用父类的构造方法,参见后续代码):
class Person(object):
def __init__(self,name,sex):
self.name = name
self.sex = sex
class Child(Person): # Child 继承 Person
def __init__(self,name,sex,mother,father):
self.name = name
self.sex = sex
self.mother = mother
self.father = father
May = Child("May","female","April","June")
print(May.name,May.sex,May.mother,May.father)
Person
若父类构造函数包含很多属性,子类仅需新增1、2个,会有不少冗余的代码,这边,子类可对父类的构造方法进行调用,参考如下:
class Person(object):
def __init__(self,name,sex):
self.name = name
self.sex = sex
class Child(Person): # Child 继承 Person
def __init__(self,name,sex,mother,father):
Person.__init__(self,name,sex) # 子类对父类的构造方法的调用
self.mother = mother
self.father = father
May = Child("May","female","April","June")
print(May.name,May.sex,May.mother,May.father)
多重继承
多重继承的概念应该比较好理解,比如现在需要新建一个类baby继承Child,可继承父类及父类上层类的属性及方法,优先使用层类近的方法,代码参考如下:
class Person(object):
def __init__(self,name,sex):
self.name = name
self.sex = sex
def print_title(self):
if self.sex == "male":
print("man")
elif self.sex == "female":
print("woman")
class Child(Person):
pass
class Baby(Child):
pass
May = Baby("May","female") # 继承上上层父类的属性
print(May.name,May.sex)
May.print_title() # 可使用上上层父类的方法
class Child(Person):
def print_title(self):
if self.sex == "male":
print("boy")
elif self.sex == "female":
print("girl")
class Baby(Child):
pass
May = Baby("May","female")
May.print_title() # 优先使用上层类的方法
总结
以上就是本文关于Python类的继承和多态代码详解的全部内容,希望对大家有所帮助。
② python中重写==的s方法
Python中对应于虚拟类的概念是抽象基类(ABC),一般类的话没有必须重写的东西。
③ 简述python面向对象编程中函数重载和重写的区别
这个基本是没有一点关联。。。只是名字容易混淆而已 重写就是对父类的方法重写,改变方法体中的语句。。。。 重载就是同一个函数名,参数个数、类型、排列顺序不同,jvm根据参数来决定调用哪一个方法
④ 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 self<other
#提供方法,判断当前集合是否为另一集合的超集
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__
⑤ Python自定义的类,为什么需要重写
首先,自定义的类在不继承任何基类的情况下,也具有__str__属性:
[python] view plain
class RoundFloatManual(object):
... def __init__(self, val):
... assert isinstance(val, float), \
... "Value must be a float!"
... self.value = round(val, 2)
rfm = RoundFloatManual(5.590464)
dir(rfm)
返回:
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__mole__', '__new__', '__rece__', '__rece_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'value']
__str__ 是 Python 类中的特殊方法,他的回传值就是使用 str(x) 所得到的值, 而 print(x) 其实就等于是print(str(x)).其实再讲细一点,当我们呼叫 str(x) 的时候其实是呼叫x.__str__()
也就是说我们可以这样想象:
print(x) === print(str(x)) === print(x.__str__())
一般我们 自定义的类,__str__ 方法的回传值是默认的字串,比如说: <__main__.Mylist object at 0x0071A470> 用以说明 namespace, class name 和位置.如果要改变__str__ 的回传值,我们必须要覆写他.
⑥ python类方法重写
从父类继承中的方法,如果不满足程序的需求,就需要重写。
方法重写指的是在子类中自定义实现父类中的同名方法。
⑦ Python中类的定义规是什么
类的概念:
类 Class: 用来描述具体相同的属性和方法的对象的集合。定义了该集合中每个对象所共有的属性和方法。对象是类的示例。
类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
实例变量:定义在方法中的变量,只作用于当前实例的类。
数据成员:类变量或者实例变量用于处理类及其实例对象的相关数据。
方法:类中定义的函数。在类内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self, 且为第一个参数,self 代表的是类的实例。
构造函数:即__init()__,特殊的方法,在对象创建的时候被自动调用。
析构函数:即__del()__,特殊的方法,在对象被销毁时被自动调用。
实例化:创建一个类的实例,类的具体对象。就是将创建的类赋值给另一个变量。理解为赋值即可,a = class(),这个过程,就叫做实例化
对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟”是一个(is-a)”关系(例图,Dog是一个Animal)。
方法重写:如果从父类继承的方法不能满足子类的需求,可以对其 进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
————————————————
原文链接:https://blog.csdn.net/f156207495/article/details/81166252
网页链接
⑧ 在Python中为什么重写__new__方法时,不需要声明它是静态方法
这个不需要纠结,就和你写的 "if" 解释器如何判断它是关键字?一个意思。
这个是解释器自己的逻辑,同样__init__()方法和其他方法也定义也没有区别,为什么实例化先会调用它,也是一个意思。
通俗点讲,你带了几个朋友回家,你要给家里人介绍一下,其中有一个朋友是你们家亲戚,那是不是就可以不用介绍了?
⑨ python怎么给导入模块的类重写其中部分类方法啊
要重写ca.py中Test类的test方法,可以这样做:
from ca import *
def t(self,mu):self.b=mu
Test.test=t
当然也可以重写__init__方法:
from ca import *
def __init__(self):self.a,self.b=0,0
Test.__init__=__init__
⑩ python 重载和重写的区别
重载和重写,这是两个新概念,是两个令我们容易混淆的概念。方法重载(overloading method)
是在一个类里面,方法名字相同,而参数不同。返回类型呢?可以相同也可以不同。方法重写(overiding method)
子类不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖。方法重载是让类以统一的方式处理不同类型数据的
一种手段。Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义。调用方法时通过传递给它们的不同个数和
类型的参数来决定具体使用哪个方法,
这就是多态性。方法重写:在Java中,子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定
的修改,这就需要采用方法的重写。方法重写又称方法覆盖。
若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。
如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类重写方法的规则:
参数列表必须完全与被重写的方法的相同,否则不能称其为重写而是重载.
返回的类型必须一直与被重写的方法的返回类型相同,否则不能称其为重写而是重载.访问修饰符的限制一定要大于被重写方法的访问修饰符
(public>protected>default>private)重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽
泛的检查型异常.例如,父类的一个方法申明了一个检查异常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。