python继承 +python多态+获取对象的信息+类中特殊的属性和方法+运算符重载+单例设计模式
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python继承 +python多态+获取对象的信息+类中特殊的属性和方法+运算符重载+单例设计模式,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含11289字,纯文字阅读大概需要17分钟。
内容图文
一、继承
1.函数的重写
override
前提:在具有继承关系的类中
作用:将父类中已有的函数在子类中进行重新的实现【声明部分一样的,实现部分不一样】
1.1系统函数的重写
注意:并不是所有的系统函数都需要重写
__str__ __repr__
代码演示:
class Person(object): def __init__(self,name,age,height,score): self.name = name self.age = age self.height = height self.score = score #3.__str__的重写:返回一个对象信息的字符串 def __str__(self): return "name=%s age=%d height=%f score=%d" % (self.name,self.age,self.height,self.score) """ def __repr__(self): return "hello" """ #4.str和repr都和对象有关,让二者的实现返回相同的结果, __repr__ = __str__可以省略 __repr__ = __str__ #等价于下面的写法: """ def __repr__(self): return "name=%s age=%d height=%f score=%d" % (self.name,self.age,self.height,self.score) """ p1 = Person("abc",19,17,37) print(p1.name,p1.score,p1.age,p1.height) #1.如果直接打印对象,获取的是对象的地址 print(p1) #<__main__.Person object at 0x000001C7E4190DD8> p2 = Person("abc",19,17,37) print(p2.name,p2.score,p2.age,p2.height) #2.函数的重写: # __str__:返回一个字符串,但是,如果没有重写该函数,默认返回该对象的地址 #当重写了__str__之后,直接使用对象,则返回的是str函数中的返回值 #print(p1.__str__()) """ 总结: a.当str和repr都未被重写的时候,使用对象,调用的是str,此时的str返回的是对象的地址 b.当str和repr都被重写之后,使用对象,调用的是str,返回的是指定的字符串 c.当没有重写str,但是,重写repr,使用对象,调用的是repr,返回的是指定的字符串 d.当只重写了str,调用是str """ #优点或者使用场景:当一个对象的属性很多,并且都需要通过打印来查看相应的值,就可以重写str函数,简化代码 p3 = Person("abc",19,17,37) print(p3)
1.2自定义函数的重写
一个父类可以有多个子类
函数重写的时机:当父类中的函数的功能不满足子类的需求时,就需要重写
注意:并不是所有的子类都需要重写父类中的函数
重写的规则;子类中出现和父类中重名的函数,则子类中的会覆盖掉父类中
代码演示:
#父类 class Animal(object): def __init__(self,name): self.name = name def show(self): print("父类~~show") #子类 class Dog(Animal): def __init__(self,name): super().__init__(name) class Cat(Animal): def __init__(self,name): super().__init__(name) class Tiger(Animal): def __init__(self,name): super().__init__(name) #重写父类中的函数 #声明相同,实现不同的 def show(self,num): #调用父类中的函数 super().show() print("子类~~~show") d = Dog("fah") d.show() t = Tiger("abc") t.show(3) #函数名就是一个变量名,重写函数的过程其实就是变量的指向发声改变的过程 #不管子类中的函数有没有参数,和父类的参数列表相不相同,不影响重写,只看函数名 #t.show()
二、多态
一种事物的多种体现形式,举例:动物有很多种
定义时的类型和运行的类型不一样,也就是说,定义时不确定调用的是哪个方法,只有运行之后才能确定调用的是哪个方法
注意:继承是多态的前提
函数的重写和运算符的重载也是多态的一种体现
代码演示:
#父类 class Animal(object): pass #子类 class Cat(Animal): pass #定义变量 a = [] b = Animal() c = Cat() #isinstance():判断一个变量是否属于指定的数据类型 print(isinstance(a,list)) print(isinstance(b,Animal)) print(isinstance(c,Cat)) #结论:在继承关系中,如果一个对象的数据类型是子类,也可以说,该对象的数据类型也是父类 print(isinstance(c,Animal)) #True #父类的对象不属于子类的数据类型 print(isinstance(b,Cat)) #False
class Dog(object): def myPrint(self): print("dog") class SmallDog(Dog): def myPrint(self): print("SmallDog") #定义时的类型和运行的类型不一样,也就是说,定义时不确定调用的是哪个方法,只有运行之后才能确定调用的是哪个方法 #temp:定义的时候temp不确定是哪种数据类型,只有运行的时候,才能确定 def show(temp): temp.myPrint() d = Dog() s = SmallDog() show(d) show(s)
三、获取对象的信息
1.type()
获取对象的数据类型
2.isinstance()
3.dir()
代码演示:
import types,os #1.type() #1.1获取类型 print(type("123")) print(type(23)) print(type(True)) print(type(None)) #注意:type返回的是对应的Class类型 print(type(type("123"))) #<class 'type'> """ <class 'str'> <class 'int'> <class 'bool'> """ #1.2比较 print(type(123) == type(56)) print(type("123") == type(123)) print(type(True) == type(False)) print(type(123) == int) print(type("abc") == str) print(type(True) == bool) #1.3判断一个对象是否是函数 #借助于types模块 print(type(abs) == types.BuiltinFunctionType) #是否是系统内置的函数 print(type((x for x in range(1,10))) == types.GeneratorType) #是否是生成器 print(type(lambda x : x) == types.LambdaType) #是否是匿名函数 def func(): pass print(type(func) == types.FunctionType) #是否是自定义函数 #2.isinstance();判断一个对象是否属于某种数据类型 print(isinstance(3,int)) print(isinstance("abc",str)) #注意:判断某个对象是否属于元组中的其中一种数据类型 或 print(isinstance([1,2,3],(list,tuple))) print(isinstance((1,2,3),(list,tuple))) #3.dir():获取任意对象的所有信息,包含从父类中继承的内容【属性和方法】 print(dir(os)) print(dir("abc")) """ 在Python中.变量的前后各有两个下划线,是有特殊用途的,比如__len__是len()在底层存在的形式 """ print(len("abc")) print("abc".__len__()) class Check(object): nanme = "gagj" def show(self): pass c = Check() print(dir(c))
四、类中特殊的属性和方法
1.实例属性和类属性
实例属性【对象属性】和类属性的区别
? a.定义的位置不同:类属性直接定义在类中,实例属性定义在构造函数中
? b.访问方式不同:实例属性必须用对象访问,类属性可以使用类名或者对象访问
? c.在内存中出现的时机不同:类属性随着类的出现而出现,实例属性随着对象的出现而出现【在代码中,类优先于对象出现的】
? d.调用的优先级不同:如果类属性和实例属性重名的情况下,对象优先调用实例属性
代码演示:
class Person(object): #1.定义的位置不同 # 类属性:直接定义在类中 name = "abc" num = 10 #实例属性:定义在构造函数中 def __init__(self,name): self.name = name #2.调用的方式 #类属性:对象.属性 或者 类名.属性 #实例属性;对象.属性 p = Person("javk") #3.优先级不同:实例属性的优先级高 print(p.name) print(Person.name) del p.name print(p.name) print(p.num) #总结;如果是多个对象的共享数据,则定义为类属性,如果是对象特有的数据,则定义为实例属性 #注意:尽量避免类属性和实例属性重名
2.动态添加属性和方法
代码演示:
from types import MethodType class Check(object): num = 0 __slots__ = ("num1","num2") def func(self): print("func") #1.动态绑定属性 c1 = Check() c1.num1 = 10 print(c1.num1) #2.动态绑定方法 """ def show(self): print("show") c1.func() #一个变量可以指向函数,该变量就可以被当做函数进行调用 c1.num2 = show #当对象调用一个成员函数的时候,self不需要手动传参的,参数表示的当前对象 c1.num2(c1) """ #使用系统的MethodType类创建一个函数 def show(self): print("show") # 参数:需要绑定的函数的名字 绑定给哪个对象 c1.num2 = MethodType(show,c1) c1.num2()
3.类方法和静态方法
类方法:在一个类中,如果一个方法被@classmethod装饰器修饰,则被称为类方法
? a.可以使用对象调用,也可以使用类名调用
? b.类方法是属于整个类的,并不属于某个对象,所以在类方法中不能出现self
? c.必须有一个参数,为cls,代表的是当前类,在类方法中可以直接通过cls创建对象,也可以通过cls直接调用当前类中的其他的类方法
静态方法:在一个类中,如果一个方法被@staticmethod装饰器修饰,则被称为静态方法
? a.类似于类方法,可以使用对象调用,也可以使用类名调用
? b.参数部分没有任何限定
代码演示:
class Check(object): #1.类属性 num1 = 0 def __init__(self,num2): #2.实例属性 self.num2 = num2 #3.成员函数:只能通过对象调用 def show(self): print("show") return 10 #4.类函数:对象或者类名调用 @classmethod def func1(cls): print("func~~~1",cls) #cls的用法;代表的是当前类,所以可以通过cls创建对象 c2 = cls(67) #通过cls创建出来的对象调用成员函数 c2.show() #5.静态方法:对象或者类名调用 @staticmethod def func2(): print("hgjhg") c1 = Check(76) c1.func1() Check.func1() #Check.show() #TypeError: show() missing 1 required positional argument: 'self' #print(type(c1)) c1.func2() Check.func2() #使用场景:类方法和静态方法 一般用于工具类的封装中
代码演示:
class SuperClass(object): @staticmethod def func2(): print("hgjhg") @classmethod def func1(cls): print("func~~~1") class SubClass(SuperClass): @staticmethod def func2(): print("子类~~~hgjhg") @classmethod def func1(cls): print("子类~~~~~func~~~1") s1 = SubClass() s1.func1() s1.func2() #结论:通过子类对象可以调用类方法和静态方法,同时也可以在子类中重写类方法和静态方法
4.常用的属性
__name__:获取类名的字符串 通过类名访问,对象访问会报错 __dict__: 通过对象访问:获取的是该对象的属性和方法,返回一个字典 通过类名访问:获取的是该类的所有的信息 __bases__:获取指定类的所有的父类 通过类名访问
代码演示:
#1.__name__ class Animal(object): num1 = 10 def __init__(self,name,age): self.name = name self.age = age @staticmethod def func2(): print("~~~hgjhg") @classmethod def func1(cls): print("~~~~~func~~~1") def func3(self): print("func3") a = Animal("abc",19) #print(a.__name__) #AttributeError: 'Animal' object has no attribute '__name__' print(Animal.__name__) #Animal #2.__dict__ print(a.__dict__) #对象.__dict__:实例属性 print(Animal.__dict__) #类名.__dict:该类中的所有的内容,除了实例属性 #3.__bases__:获取父类,返回是一个元组 #print(a.__bases__) #AttributeError: 'Animal' object has no attribute '__bases__' print(Animal.__bases__)
五、运算符重载
overload
重载:两个类,如果在 一个类中重新实现了一个方法
对专有的方法进行重载
代码演示:
#+普通用法 #数字和数字相加:数学运算 print(24 + 49) #字符串和字符串相加:拼接 print("fdh" + "ghaur") #print("ahfg" + 16) #ypeError: must be str, not int #不同的数据类型的加法操作会有不同的解释 class Person(object): def __init__(self,num): self.num = num def __str__(self): return "num = " + str(self.num) #运算符重载 #在程序中,但凡涉及到+运算,在底层都会调用__add__, def __add__(self, other): return Person(self.num + other.num) p1 = Person(23) p2 = Person(12) print(p1,p2) #int+int = int str+str = str person+person = person p3 = p1 + p2 print(p3) print(p3.__str__()) #35 print(p1.__add__(p2)) #p1 + p2 =====>p1.__add__(p2) """ def text(str1,num1): return str1 + str(num1) text("abc" + 18) """ #使用场景:当系统的某些功能满足不了需求时,就可以在类中进行重载,函数的实现体部分完全可以自定义
六、单例设计模式
1.案例
小彩旗,见代码
2.概念
什么是设计模式?
? 设计模式是别人已经总结好的可以解决问题的方案
? 设计模式23种,常用的是单例设计模式,工厂设计模式,生产者消费者设计模式,代理委托设计模式等
什么是单例设计模式?
? 单例:单个的实例,单个的对象
? 程序在运行的过程中,确保某一个类只能有一个实例【对象】,不管在程序的哪个位置获取,获取到的都是同一个对象
单例设计模式的核心;一个类有且只能有一个对象,并且该对象可以应用于整个程序中
3.使用
3.1使用new
类似于构造函数,优先于构造函数
代码演示:
#__new__:在__init__之前创建对象 class Sigleton(object): #定义一个类属性【可以通过类名】 #作用:用于返回当前类的实例 instance = None #重写new函数 def __new__(cls, *args, **kwargs): #将当前类的对象和instance变量联系起来 #思路;如果cls.instance为None,则创建对象并赋值,如果不为None,则直接返回对象 if not cls.instance: cls.instance = super(Sigleton,cls).__new__(cls,*args, **kwargs) return cls.instance s1 = Sigleton() s2 = Sigleton() s3 = Sigleton() print(id(s1) == id(s2)) #True print(id(s1) == id(s3)) print(s1 is s2)
3.2装饰器
代码演示:
#装饰器:作用于一个函数,也可以作用域一个类 def sigleton(cls): instance = {} #getInstance/defaultxxx/ currentxxx def getInstance(*args, **kwargs): #思路1:可以类似于new,通过是否为NOne #思路2:将cls作为key,cls对应的实例作为value存储到字典中 if cls not in instance: instance[cls] = cls(*args, **kwargs) #dict[key] = value return instance[cls] return getInstance @sigleton class Test(object): pass t1 = Test() t2 = Test() print(id(t1) == id(t2)) print(t1 is t2)
3.3自定义类
代码演示:
class Check(object): instance = None @classmethod def getInstance(cls,*args, **kwargs): if not cls.instance: cls.instance = cls(*args, **kwargs) return cls.instance c1 = Check.getInstance() c2 = Check.getInstance() c3 = Check() print(id(c1) == id(c2)) print(c1 is c2) print(c1 is c3) #False #弊端:还是可以通过类名创建对象,但凡在类外面创建的对象,都属于不同的对象
内容总结
以上是互联网集市为您收集整理的python继承 +python多态+获取对象的信息+类中特殊的属性和方法+运算符重载+单例设计模式全部内容,希望文章能够帮你解决python继承 +python多态+获取对象的信息+类中特殊的属性和方法+运算符重载+单例设计模式所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。