一。多态

  在现实生活中,多态也会体现。如对于水这种物质,有固态:冰,液态:常态,气态:水蒸气,

  在程序中,其官方定义是:多个不同对象可以相应同一方法,产生不同的结果。

  而在python中,多态不是一个特殊的语法,而是一种关系,一种特性,举例:

class A:
def work(self):
print('I am working in A') def name(self):
print('i am A') class B:
def work(self):
print('I am working in B') def name(self):
print('i am B') class C:
def work(self):
print('I am working in C') def name(self):
print('i am C') a=A()
b=B()
c=C()
def toge(obj):
obj.work() toge(a)
toge(b)
toge(c)
#I am working in A
#I am working in B
#I am working in C

  上述代码中分别制造了ABC三个类,这三个类都有不同 的特征,也有相同的特征work,可以通过多态,统一管理其中的work使之工作而保留其他的特性。

  这种方法在接口中有所体现是,所以除了上述的鸭子类型以外也可以使用接口和抽象类来使用多态。

  如果不是这种特性,需要分别对ab三个对象编写其对应的方法。

二。相关内置对象

  1.isinstance

  作用:判断某个对象是否是某个类的实例:isinstance(对象,类)

  这种方法也可以判断某个数据是否是某个类型isinstance(数据,类型)

class Person:
def work(self):
print('i am working ') class book:
def write(self):
print('i can write') def working(oop):
if isinstance(oop,Person):
oop.work()
else:
print('you are not Person') ab=Person()
ac=book()
working(ab)
working(ac)
#i am working
#you are not Person

  当一个对象不具有某个特点时,可以使用isinstance来判断是否可以执行该函数,使程序不会报错,因为可以不执行不存在的方法。

  除此之外,isinstance还可以判断某个数据是不是某个数据类型:

def add(a,b):
if isinstance(a,int) and isinstance(b,int):
return a+b
else:
return '不是整型' print(add(2,44))
print(add('asd',2))
#
#不是整型

  2.issubclass(子类,父类)

  作用,判断一个子类是不是某个父类的子类。

class Father:
def name(self):
print('i am father') class Son(Father):
def name(self):
print('i am son') class Wang:
def name(self):
print('i am wang ') def test1(oop):
if issubclass(type(oop),Father):
oop.name()
else:
print('you are not my son') s1=Son()
w1=Wang()
test1(s1)
test1(w1)
#i am son
#you are not my son

三。魔法函数

  这类方法一般都放在类中使用。

  1.__str__

  该方法是在对象被转化为字符串时触发,而对象本来是一种对象形式:

<__main__.Person object at 0x00000288BDA380B8>

  而这种方法显然是没有什么意义的,但是对于print的原理就是先将任何数据转化成字符串形式打印出来,所以,如果定义了该方法之后就可以直接打印该对象。

  在__str__方法中可以传入对象参数,规定打印格式,如:

class Person:
def __init__(self,name,age):
self.name=name
self.age=age def __str__(self):
return '名字是%s,年龄是%s'%(self.name,self.age) p1=Person('lzx',18)
print(p1)
#名字是lzx,年龄是18

  2.__del__

  该方法是在对象被删除时,执行该方法:

class Person2:
def __init__(self,name,age):
self.name=name
self.age=age def __del__(self):
print('i am del') a=Person2('lzx',123)
del a
print('over')
#i am del
#over

  当执行del a与据说是,会打印iam del

  但是如果不执行del a 语句,程序会自动结束,垃圾回收机制会自动将不用的对象进行回收删除,所以即使不写这句话,在最后也会执行语句。

  简易文件处理:

class File1:
def __init__(self,file):
self.file=open(file,'r',encoding='utf-8') def read(self):
return self.file.read() def __del__(self):
self.file.close()
print('over') ab=File1('test.py')
print(ab.read())

  在对象结束时自动关闭对文件的操作。

  3.__call__

  当对象被调用时,执行该函数,调用就是对象名+()

class Test2:
def __call__(self, *args, **kwargs):
print('') ba=Test2()
ba()
#

  4.__slots__

  该属性是一个类属性,在类中使用,用于内存优化,当一个类定义了__slots__后,会使得类中的名称空间不被创建,类中只能创建slots中所用有的名称属性,不能多也不能少,这样就能减少内存开销的效果。

  __slots__=['','']

class Person:

    __slots__ = ["name"]
def __init__(self,name):
self.name = name p = Person("jck") # 查看内存占用
# print(sys.getsizeof(p))
# p.age = 20 # 无法添加 # dict 没有了
print(p.__dict__)

  注意,这时候的Person中的__dict__已经不存在了。

  5.getattr setattr delattr

  getattr 用点访问属性的时如果属性不存在时执行

  setattr 用点设置属性时

  delattr 用del 对象.属性 删除属性时 执行

class Test3:
def __getattr__(self, item):
print('__getattr__')
return 1 def __setattr__(self, key, value):
print('__setattr__')
self.__dict__[key]=value def __delattr__(self, item):
print('__delattr__')
self.__dict__.pop(item) abc=Test3()
print(abc.name)
abc.name=''
print(abc.name)
del abc.name
print(abc.name)
#__getattr__
#
#__setattr__
#
#__delattr__
#__getattr__
#

  首先,除了使用super继承父类的方法运行程序实现功能之外,对于setattr的基本原理就是将键值添加至名称空间的字典__dict__里,在设置属性时调用。而删除也是将名称空间字典中的键值弹出,顺便执行该函数语句。

  而getattr,当可以通过点获取该值时,就返回该值,当没有找到该值时就返回return中的值

  getattribute

  当类中有getattribute方法时,获取值前会优先执行该函数,如果获取到了属性,就会返回其值,如果没有找到,就会调用getattr方法。

class Test3:
def __getattr__(self, item):
print('__getattr__')
return 1 def __getattribute__(self, item):
print('__getattribute__')
return super().__getattribute__(item) abc1=Test3()
# abc1.name=123
print(abc1.name)
#__getattribute__
#__getattr__
#

  6.getitem,setitem,delitem

  当类中有上述发方法,使用[]获取其值时,会触发该函数。

class Test4:
def __getitem__(self, item):
print('__getitem__')
return self.__dict__[item] def __setitem__(self, key, value):
print('__setitem__')
self.__dict__[key]=value def __delitem__(self, key):
print('__delitem__')
del self.__dict__[key] abc4=Test4()
abc4['name']=22
print(abc4['name'])
del abc4['name']
print(abc4['name'])
#__setitem__
#__getitem__
#
#__delitem__

  了解即可。

  例:让一个对象既支持点取值,又支持[]取值:

class MyDict(dict):

     def __getattr__(self, key):
return self.get(key) def __setattr__(self, key, value):
self[key] = value def __delattr__(self, item):
del self[item]

  在该类中,首先继承了dict类的方法,使得对象可以用于字典的属性,再对其点操作进行返回值。

  7.运算符重载(__gt__,__lt__,__eq__)

  gt是在对象之间进行比较大时,运行该函数

  lt是在对象之间进行比较小时,运行该函数

  eq是在对象之间进行比较等于时,运行该函数

  本来对象之间是不支持运算符比较 的(等于可以比较)

class Test6:
def __init__(self,name,age):
self.name=name
self.age=age a=Test6('lzx',6)
b=Test6('zzp',3)
print(a>b)
#报错

  进行等于比较时也是比较两个对象是否相同。

  而使用gt或者lt就可以实现对象之间的属性值的比较:

class Test6:
def __init__(self,name,age):
self.name=name
self.age=age def __gt__(self, other):
if self.age>other.age:
return True
return False def __lt__(self, other):
if self.age<other.age:
return False
return True def __eq__(self, other):
if self.age==other.age:
return 123
return 321 a=Test6('lzx',6)
b=Test6('zzp',3)
print(a<b)
print(a==b)
#True
#

  当然,在gt和lt之间只需要使用一个就够了。符号如果不同 解释器会自动交换两个对象的位置。

四。迭代器

  要使一个类或对象,成为一个迭代器,需要在其定义两个方法:__item__和__next__。

class Dd:
def __init__(self,max):
self.max=max
self.count=0 def __iter__(self):
return self def __next__(self):
if self.count<self.max:
self.count+=1
return self.count
else:
raise StopIteration for i in Dd(10):
print(i)

  Dd就使一个迭代器,Dd的作用就是输入1-10的数,当调用该类时,执行next中的语句,使用StopItIreration进行异常抛出,停止程序,防止死循环的出现。

  利用这个可以模仿range函数:

class Myrange:
def __init__(self,min1,max1,step=1):
self.min1=min1-1
self.max1=max1-1
self.step=step def __iter__(self):
return self def __next__(self):
if self.min1<self.max1:
self.min1+=self.step
return self.min1
else:
raise StopIteration for i in Myrange(0,10,2):
print(i)

  如上,range满足左开右闭原则,而步长step默认为1,即使不传也没关系,不同点在于必须要传入起始数字。

  所以,可以把具有__iter__,__next__两个方法的类看作一个迭代器。

五。上下文操作

  上下文操作其实早有应用,像文件的打开与写入就是上下文操作,在使用with操作文件时会获取一个文件句柄,对句柄进行操作,即使后来忘记关闭对文件的链接,最后程序也会自动帮你关闭,其原理 就是在open类中的exit函数帮你关闭文件。

  当执行with语句时,会先执行enter语句,如果运行正常,则运行exit语句,当enter运行过程中出现异常,则会立即运行exit语句,并传入异常信息。

class Text7:
def __init__(self,file):
self.file=file def __enter__(self):
print('enter===')
self.f=open(self.file)
return self.f def __exit__(self, exc_type, exc_val, exc_tb):
print('exit===')
print(exc_type, exc_val, exc_tb)
self.f.close() with Text7('test.py') as m:
print(m.read())

  Text7就是一个低配的open操作,其中:

  enter将文件句柄作为返回值给类。

  在exit中exc_type, exc_val, exc_tb,三个参数就是返回其异常信息(包含错误的类型.错误的信息.错误的追踪信息)。

  小知识:exit也有返回值,返回的是一个布尔值(True,False),当程序正常运行结束时,没有太大影响,

      当程序出现异常时,如果返回值是true时,异常会被处理,如果返回的时False。异常会被保留。

day23_7.29 多态和类的内置方法的更多相关文章

  1. day28 面向对象:反射,内置函数,类的内置方法

    面向对象进阶博客地址链接: http://www.cnblogs.com/Eva-J/articles/7351812.html 复习昨日内容: # 包 # 开发规范 # # hashlib # 登录 ...

  2. python学习之老男孩python全栈第九期_day027知识点总结——反射、类的内置方法

    一. 反射 ''' # isinstance class A:pass class B(A):pass a = A() print(isinstance(a,A)) # 判断对象和类的关系 print ...

  3. Python进阶-XVIV 类的内置方法:__str__ 、__repr__、析构函数(__del__)、双下的call,eq,new,hash 以及item相关的三个方法

    类的内置方法 它与内置函数有紧密的联系,有的内置函数就是调用的内置方法. 在顶级父类obj中有: 两个双下方法 obj.__str__ str(obj) obj.__repr__ repr(obj) ...

  4. python基础语法18 类的内置方法(魔法方法),单例模式

    类的内置方法(魔法方法): 凡是在类内部定义,以__开头__结尾的方法,都是类的内置方法,也称之为魔法方法. 类的内置方法,会在某种条件满足下自动触发. 内置方法如下: __new__: 在__ini ...

  5. CSIC_716_20191129【面向对象高级----反射、类的内置方法(魔法方法)、单例模式】

    反射 反射是通过'字符串'对 对象的属性进行操作,反射有四个内置的方法. hasattr 通过字符串 判断对象的属性或者方法是否存在 getattr 通过字符串  获取对象的属性或者方法        ...

  6. python -- 类中--内置方法

    isinstance 和  issubclass isinstance(obj,b)  检查是否obj是否是类b的对象 class A(object):pass class B(A):pass b=B ...

  7. 第8.14节 Python类中内置方法__str__详解

    一. object类内置方法__str__和函数str 类的内置方法__str__和内置函数str实际上实现的是同一功能,实际上str调用的就是__str__方法,只是调用方式不同,二者的调用语法如下 ...

  8. 第8.13节 Python类中内置方法__repr__详解

    当我们在交互环境下输入对象时会直接显示对象的信息,交互环境下输入print(对象)或代码中print(对象)也会输出对象的信息,这些输出信息与两个内置方法:__str__方法和__repr__方法有关 ...

  9. 多态 鸭子类型 反射 内置方法(__str__,__del__) 异常处理

    ''' 1什么是多态 多态指的是同一种/类事物的不同形态 2 为何要有多态 多态性:在多态的背景下,可以在不用考虑对象具体类型的前提下而直接使用对象 多态性的精髓:统一 多态性的好处: 1增加了程序的 ...

随机推荐

  1. 剑指Offer-11.二进制中1的个数(C++/Java)

    题目: 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 分析: 将数字和1先做与运算,然后将1右移一位,现在是判断数字的第二位是不是1,这样循环的做下去即可.也可以转换成字符串再统计 ...

  2. Codeforces Round #596 (Div. 2, based on Technocup 2020 Elimination Round 2) C. p-binary 水题

    C. p-binary Vasya will fancy any number as long as it is an integer power of two. Petya, on the othe ...

  3. MySQL实战45讲学习笔记:第二十七讲

    一.一主多从的切换正确性 在前面的第24.25和26篇文章中,我和你介绍了 MySQL 主备复制的基础结构,但这些都是一主一备的结构. 大多数的互联网应用场景都是读多写少,因此你负责的业务,在发展过程 ...

  4. .Net Framework与.Net Core文件系统的差异

    在.Net Fx下,可通过try/catch实例化DirectoryInfo/FileInfo来判断用户输入的路径是否合法,但我把代码拷到 .Net Core 下运行,发现运行结果完全不同 var d ...

  5. CSP-S 2019 题解

    D1T1-格雷码 题中给出了构造格雷码的方法. $solve(n,k)$表示求出$2^n$意义下排名为$k$的格雷码, 只要比较一下考虑最高位的0/1取值就好了. 部分分提示了要开$unsigned\ ...

  6. ubuntu16.04安装QGIS工具

    指令安装安装qgis可以通过添加安装源的形式进行 sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable sudo apt-get updat ...

  7. ELK学习笔记之Elasticsearch删除指定日期的数据(脚本+定时任务)

    0x00 概述 目前使用的ES版本为6.3.x,经过长时间的积累,ES内数据越来越多,需要删除指定日志之前的日志. 例如只要求保留60天的日志,那么就要删除60天之前的所有索引和日志. 0x01 ES ...

  8. 【JS】---5 JS通过事件隐藏显示元素

    JS通过事件隐藏显示元素 在开发中,很多时候我们需要点击事件,才显示隐藏元素.那如何做到页面刚开始就把标签隐藏. 有两种方法: (1) display:none    <div id=" ...

  9. 3-Consul 使用手册

    原文:http://www.liangxiansen.cn/2017/04/06/consul/ Consul包含多个组件,但是作为一个整体,为你的基础设施提供服务发现和服务配置的工具.他提供以下关键 ...

  10. 实战Rest API接口测试

    一.Android App API接口测试 1.如何学好Android App API接口测试 postman可以用来实现API接口自动化测试,但是也有弊端,无法实现接口测试数据的参数化,为了达到接口 ...