isinstance()

判断isinstance(obj,cls)中obj是否是cls类的对象

class Person:
def __init__(self,name):
self.name = name
p = Person('Jane')
print(isinstance(p,Person))   #True

issubclass()

判断issubclass(sub,super)中sub是否是super类的派生类

class Person:
def __init__(self,name):
self.name = name
class Father(Person):
pass
print(issubclass(Father,Person)) #True
print(issubclass(Person,Father)) #False

反射

反射就是用字符串类型的名字去操作变量,python中的一切事物皆为对象(都可以使用反射)

1.hasattr()

函数用于判断对象是否包含对应的属性,通常和getattr一起搭配使用,先用hasattr判断是否这个对象含有这个属性,如果有就通过getattr来拿值,如果没有就提示没有这个属性

class Person:
age = 20
def __init__(self,name,height,weight):
self.name = name
self.height = height
self.weight = weight
def fuc(self):
print('weight...height...')
#1
if hasattr(Person,'age'):
print(getattr(Person,'age')) #
else:
print('没有这个类属性!')
#2
p = Person('Adson',1.6,75)
if hasattr(p,'bmi'):
print(getattr(p,'bmi'))
else:
print('没有这个属性!')   #没有这个属性!
#3
if hasattr(p,'fuc'):
getattr(p,'fuc')() #weight...height...
else:
print('没有这个方法!')

2.getattr()

函数用于返回一个对象属性值

(1)反射对象的属性

class A:
def __init__(self,name):
self.name = name
a = A('Adson')
ret = getattr(a,'name')
print(ret) #Adson

(2)反射对象的方法

class A:
def fuc(self):
print('This is fuc!')
a = A()
ret = getattr(a,'fuc')
print(ret) #<bound method A.fuc of <__main__.A object at 0x00000000024E1C88>>  获得一个绑定方法的地址
ret() #This is fuc!   在ret后加上括号去调用方法

(3)反射类的属性

class A:
age = 18
ret = getattr(A,'age')
print(ret)    #

(4)反射类的方法(classmethod、staticmethod)

一般的调用方式是类名.方法名

class A:
@classmethod
def fuc(cls):
print('This is class fuc!')
ret = getattr(A,'fuc')
print(ret) #<bound method A.fuc of <class '__main__.A'>> 获得一个绑定方法
ret() #This is class fuc!
getattr(A,'fuc')() #This is class fuc! 简写

(5)反射模块的变量

先建立一个模块,模块名pyfile.py,增加一个变量

dic = {'apple' : 18,'banana' : 20}

然后通过我的模块反射pyfile模块的变量

import pyfile
print(pyfile.dic)          #{'apple': 18, 'banana': 20}
ret = getattr(pyfile,'dic')
print(ret)          #{'apple': 18, 'banana': 20}

(6)反射模块的方法

先建立一个模块,模块名pyfile.py,增加一个方法

def fuc():
print('abc123aaa!!!')

然后通过我的模块反射pyfile模块方法

import pyfile
ret = getattr(pyfile,'fuc')
print(ret)            #<function fuc at 0x0000000002498D08>
ret()            #abc123aaa!!!
getattr(pyfile,'fuc')()            #abc123aaa!!!

(7)反射模块的类

先建立一个模块,模块名pyfile.py,增加一个类

class B:
price = 200
def __init__(self,name):
self.name = name
def fuc(self):
print('This classB fuc..' + self.name)

然后通过我的模块反射pyfile模块方法

import pyfile
b = getattr(pyfile,'B')('Josn')        #getattr相当于拿到了这个模块的B类 并进行实例化了一个b对象
print(b.__dict__)        #{'name': 'Josn'}
print(b.price)        #
b.fuc()        #This classB fuc..Josn

(8)反射自身模块的变量

通过sys.modules['__main__']找到当前的模块

import time
import sys
t = time.asctime(time.localtime(time.time()))
print(t) #Mon Sep 9 22:36:40 2019
print(sys.modules['__main__']) #<module '__main__' from 'C:/Users/Administrator/PycharmProjects/PYL/temp_file/temp_py.py'>
print(sys.modules['__main__'].t) #Mon Sep 9 22:38:01 2019
ret = getattr(sys.modules['__main__'],'t')
print(ret) #Mon Sep 9 22:39:05 2019

(9)反射自身模块的方法

import sys
def fuc():
print('abc123...')
ret = getattr(sys.modules['__main__'],'fuc')
print(ret)   #<function fuc at 0x0000000002798730>
ret()   #abc123...
getattr(sys.modules['__main__'],'fuc')()   #abc123...

3.setattr()

用于设置属性值,该属性不一定是存在的

class Person:
age = 20
def __init__(self,name,height,weight):
self.name = name
self.height = height
self.weight = weight
#对一个对象修改
p = Person('Adson',1.6,75)
setattr(p,'name','Jane')
setattr(p,'height',1.7)
setattr(p,'gender','male')
print(p.__dict__) #{'name': 'Jane', 'height': 1.7, 'weight': 75, 'gender': 'male'}
#对一个类修改
print(Person.__dict__) #{'__module__': '__main__', 'age': 20, '__init__': <function Person.__init__ at 0x0000000002548950>,
                       '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__':
                       <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
setattr(Person,'age',21)
setattr(Person,'name','Jane')
setattr(Person,'height',1.7)
setattr(Person,'gender','male')
print(Person.__dict__) #{'__module__': '__main__', 'age': 21, '__init__': <function Person.__init__ at 0x0000000002548950>,
                       '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__':
                       <attribute '__weakref__' of 'Person' objects>, '__doc__': None,
                       'name': 'Jane', 'height': 1.7, 'gender': 'male'}

这里的不同之处在于对象和类它们存放值的命名空间不同

4.delattr()

用于删除属性

class Person:
age = 20
def __init__(self,name,height,weight):
self.name = name
self.height = height
self.weight = weight
p = Person('Adson',1.6,75)
print(p.__dict__) #{'name': 'Adson', 'height': 1.6, 'weight': 75}
delattr(p,'height')
print(p.__dict__) #{'name': 'Adson', 'weight': 75}
print(Person.__dict__['age']) #
delattr(Person,'age')
print(Person.__dict__['age']) #KeyError: 'age'

内置类方法

内置的类方法和内置函数之间有着千丝万缕的关系

1.__str__

当我们定义一个类,并实例化一个对象,再对这个对象去print

class A:
def __init__(self,name,price,types):
self.name = name
self.price = price
self.types = types
a = A('AAA',200,'A')
print(str(a)) #<__main__.A object at 0x00000000020D7A58>

这里返回了这个对象的内存地址,我们再在A类里面添加一个__str__方法,看一看结果是什么

class A:
def __init__(self,name,price,types):
self.name = name
self.price = price
self.types = types
def __str__(self):
return 'name = %s,price = %s,types = %s'%(self.name,self.price,self.types)
a = A('AAA',200,'A')
print(a)         #name = AAA,price = 200,types = A

可以这么说我们在每次打印一个对象的时候就是在调用obj.__str__,且__str__方法需要返回一个字符串,当做这个类的描写;当我们使用print这个对象时会打印出__str__方法return出来的字符串

2.__repr__

先说一下repr()方法,它能让我们输入的数据原形毕露

print(repr(1))                  #
print(repr('')) #'1'
print(repr('aaa')) #'aaa'
print(repr({'a':1,'b':2})) #{'a': 1, 'b': 2}

和__str__一样我们在定义一个类后去print它实例化的对象,会获得到一个对象的内存地址

class A:
def __init__(self,name,price,types):
self.name = name
self.price = price
self.types = types
a = A('AAA',200,'A')
print(repr(a))    #<__main__.A object at 0x00000000024E7A58>

然后我们再在A中添加__repr__方法看一下print的结果

class A:
def __init__(self,name,price,types):
self.name = name
self.price = price
self.types = types
def __repr__(self):
return 'name = %s,price = %s,types = %s' % (self.name, self.price, self.types)
a = A('AAA',200,'A')
print(repr(a)) #name = AAA,price = 200,types = A
print(a) #name = AAA,price = 200,types = A

因为我们在类中定义了一个__repr__方法,这里我们print对象a的时候就相当于是调用了里面的__repr__方法即a.__repr__

如果一个类中的__str__和__repr__同时存在的话,那么最后的打印结果是什么呢?

class A:
def __init__(self,name,price,types):
self.name = name
self.price = price
self.types = types
def __str__(self):
return 'str(name = %s,price = %s,types = %s)'%(self.name,self.price,self.types)
def __repr__(self):
return 'repr(name = %s,price = %s,types = %s)' % (self.name, self.price, self.types)
a = A('AAA',200,'A')
print(repr(a)) #repr(name = AAA,price = 200,types = A) 即a.__repr__
print('%r'%a) #repr(name = AAA,price = 200,types = A)
print(str(a)) #str(name = AAA,price = 200,types = A) 即a.__str__
print('%s'%a) #str(name = AAA,price = 200,types = A)
print(a) #str(name = AAA,price = 200,types = A)

如果一个类中有__str__方法,那么它就会先找__str__,没有的话就再找__repr__方法,再没有的话就会找它父类的__str__方法

__str__方法和__repr__方法能够返回该对象一个规范化的信息

3.__len__

我们将一个实例化的对象直接print它的len看一看会出现什么结果

class A:
def __init__(self,name,price,types):
self.name = name
self.price = price
self.types = types
a = A('AAA',200,'A')
print(len(a))     #TypeError: object of type 'A' has no len()

结果报错说A少了一个len函数,也就是我们只有在A中加上一个__len__的方法才能去计算长度相关的东西

计算属性的长度:

class A:
def __init__(self,name,price,types):
self.name = name
self.price = price
self.types = types
def __len__(self):
return len(self.name)
a = A('AAA',200,'A')
print(len(a)) #

计算一个列表属性有几个元素:

class A:
def __init__(self,goods = []):
self.goods = []
def __len__(self):
return len(self.goods)
a = A()
print(len(a)) #
a.goods.append('Banana')
a.goods.append('Apple')
a.goods.append('Orange')
a.goods.append('Pear')
print(len(a)) #

4.__call__

用于打印这个对象的属性

class A:
gender = 'male'
def __init__(self,name,price,types):
self.name = name
self.price = price
self.types = types
def __call__(self, *args, **kwargs):
return self.name,self.price,self.types,self.gender
a = A('AAA',200,'A')
print(a()) #('AAA', 200, 'A', 'male')
print(A('AAA',200,'A')()) #('AAA', 200, 'A', 'male')

5.__eq__

class A:
__instance = False
def __init__(self,name,age,height):
self.name = name
self.age = age
self.height = height
def __eq__(self, other):
if self.name == other.name and self.height == other.height:
return True
else:
return False
a1 = A('Jane',20,55)
a2 = A('Jane',18,55)
print(a1 == a2) #True

6.__hash__

控制对象中的哈希值和另外一个对象的哈希值是否相等

class A:
def __init__(self,name,age,height):
self.name = name
self.age = age
self.height = height
def __hash__(self):
return hash(self.age + self.height) + hash(self.name)
a1 = A('Jane',20,55)
a2 = A('Jane',18,55)
print(hash(a1)) #-1393240518857837779
print(hash(a2)) #-1393240518857837781

7.__new__

创建一个对象

class A:
height = 18
def __init__(self):
self.name = 'Aane'
self.price = 300
self.types = 'aaa'
def __new__(cls, *args, **kwargs):
print('实例化一个对象...')
return object.__new__(cls, *args, **kwargs)
a = A() #实例化一个对象...
print(a.__dict__) #{'name': 'Aane', 'price': 300, 'types': 'aaa'}

单例模式:限制一个类始终只有一个实例,因为一般来讲一个类可以产生无数个对象

在这里我们创建三个对象并打印它们的内存地址可以发现它们是不同的

class A:
def __init__(self):
self.name = 'aaa'
a1 = A()
a2 = A()
a3 = A()
print(a1) #<__main__.A object at 0x00000000025B1D68>
print(a2) #<__main__.A object at 0x00000000025CD0F0>
print(a3) #<__main__.A object at 0x00000000025CD128>

所以在我们第一次实例化这个类的时候就创建一个实例化的对象,那么我们再一次实例化一个对象的话该如何再去使用之前的实例化对象呢?

class A:
__instance = False
def __init__(self,name,age):
self.name = name
self.age = age
def __new__(cls,*args,**kwargs):
if cls.__instance:
return cls.__instance
cls.__instance = object.__new__(A)
return cls.__instance
a1 = A('Jogn',33)
a2 = A('Jane',35)
a3 = A('KKK',55)
print(a1) #<__main__.A object at 0x000000000217D198>
print(a1.__dict__) #{'name': 'KKK', 'age': 55}
print(a2) #<__main__.A object at 0x000000000217D198>
print(a2.__dict__) #{'name': 'KKK', 'age': 55}
print(a3) #<__main__.A object at 0x000000000217D198>
print(a3.__dict__) #{'name': 'KKK', 'age': 55}
print(id(a1),id(a2),id(a3)) #41734552 41734552 41734552

8.__del__

析构函数:当对象结束其生命周期,如对象所在的函数已调用完毕时,系统自动执行析构函数,它往往用来做"清理善后"的工作。当我们直接删除一个实例化的对象再去打印它,就会报错告诉我们这个对象已经不存在了

class A:
def __init__(self,name,price,types):
self.name = name
self.price = price
self.types = types
a = A('AAA',200,'A')
del a
print(a) #NameError: name 'a' is not defined

我们再在A中添加一个__del__方法

class A:
def __init__(self,name,price,types):
self.name = name
self.price = price
self.types = types
def __del__(self):
print('这个对象%s已被删除!' % self.name)
del self
a = A('AAA',200,'A')
del a #这个对象AAA已被删除! 这里相当于调用了a.__dict__
print(a) #NameError: name 'a' is not defined

8.__getitem__

模拟字典的方式来拿值

class A:
gender = 'male'
def __init__(self,name,price,types):
self.name = name
self.price = price
self.types = types
def __getitem__(self, item):
if hasattr(self,item):
return getattr(self,item)
return '没有找到这个值!'
a = A('AAA',200,'A')
print(a['name']) #AAA
print(a['price']) #
print(a['types']) #A
print(a['gender']) #male
print(a['sex']) #没有找到这个值!

9.__setitem__

模拟字典的方式来设值

class A:
def __init__(self,name,price,types):
self.name = name
self.price = price
self.types = types
def __setitem__(self,key,value): #重新设定一个新的值
self.__dict__['key'] = value
a = A('AAA',200,'A')
print(a.__dict__) #{'name': 'AAA', 'price': 200, 'types': 'A'}
a.__dict__['name'] = 'BBB'
a.__dict__['price'] = 300
a.__dict__['types'] = 'C'
a.__dict__['gender'] = 'male' #增加了一个新的属性gender
print(a.__dict__) #{'name': 'BBB', 'price': 300, 'types': 'C', 'gender': 'male'}

10.__delitem__

模拟字典的方式来删除

class A:
gender = 'male'
def __init__(self,name,price,types):
self.name = name
self.price = price
self.types = types
def __delitem__(self, key):
print('%s已删除!'%key)
del self.__dict__[key]
a = A('AAA',200,'A')
del a['name'] #name已删除!
del a['price'] #price已删除!
print(a.__dict__) #{'types': 'A'}

问题总结

1.有很多对象,它们的姓名和性别相同但是年龄不同,如何这种情况的对象去重?

class A:
def __init__(self,name,sex,age):
self.name = name
self.sex = sex
self.age = age
def __eq__(self, other):
if self.name == other.name and self.sex == other.sex:
return True
return False
def __hash__(self):
return hash(self.name+self.sex)
a = A('Json','male',26)
b = A('Json','male',30)
print(set((a,b))) #set()依赖对象的 __eq__和__hash__ {<__main__.A object at 0x0000000002761DD8>}

2.扑克牌问题

import json
from collections import namedtuple
Card = namedtuple('Card',['rank','suit']) #rank牌面的大小 suit牌面的花色
class FrenchDeck:
ranks = [str(n) for n in range(2,11)] + list('JQKA')
suits = ['红心','方块','梅花','黑桃']
def __init__(self):
self._cards = [Card(rank,suit) for rank in FrenchDeck.ranks for suit in FrenchDeck.suits] def __len__(self):
return len(self._cards) def __getitem__(self, item):
return self._cards[item] def __setitem__(self,key,value):
self._cards[key] = value def __str__(self):
return json.dumps(self._cards,ensure_ascii=False) deck = FrenchDeck()
print(deck[10]) #Card(rank='4', suit='梅花')
from random import choice
print(choice(deck)) #Card(rank='3', suit='方块')
print(choice(deck)) #Card(rank='9', suit='方块')
from random import shuffle
shuffle(deck)
print(deck[10]) #Card(rank='2', suit='方块')
print(deck) #打印所有牌色
print(deck[:5]) #[Card(rank='6', suit='梅花'), Card(rank='3', suit='方块'), Card(rank='10', suit='红心'),
              #Card(rank='9', suit='红心'), Card(rank='4', suit='方块')]

Python学习日记(二十七) 反射和几个内置函数的更多相关文章

  1. python学习笔记(五):装饰器、生成器、内置函数、json

    一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里 ...

  2. python学习 day12 (3月18日)----(装饰器内置函数)

    读时间函数: # import time # def func(): # start_time = time.time() # 代码运行之前的时间 # print('这是一个func函数') # ti ...

  3. python学习笔记之装饰器、生成器、内置函数、json(五)

    一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里面 ...

  4. 【Python全栈笔记】04 [模块二] 18 Oct lambda表达式, 内置函数

    lambda表达式 lambda表达式是函数的一种简化,如下面两种函数定义方法,实际上效果是一样的. 使用lambda表达式的函数,func2是函数名,lambda: 后面的123 即为返回值. de ...

  5. Python小白学习之路(十六)—【内置函数一】

    将68个内置函数按照其功能分为了10类,分别是: 数学运算(7个) abs()   divmod()  max()  min()  pow()  round()  sum() 类型转换(24个) bo ...

  6. python成长之路第三篇(3)_内置函数及生成器迭代器

    打个广告欢迎加入linux,python资源分享群群号:478616847 目录: 1.lambda表达式 2.map内置函数 3.filter内置函数 4.reduce内置函数 5.yield生成器 ...

  7. python之类的多态(鸭子类型 )、封装和内置函数property

    一.多态 1.什么是多态:一个类表现出的多种状态--->通过继承来实现的例如:class Animal:passclass Dog(Animal):passclass Cat(Animal):p ...

  8. 【Python】从简单案列中揭示常用内置函数以及数据类型

    前面提到了BIF(内置函数)这个概念,什么是内置函数,就是python已经定义好的函数,不需要人为再自己定义,直接拿来就可以用的函数,那么都有哪些BIF呢? 可以在交互式界面(IDLE)输入这段代码, ...

  9. 人生苦短之我用Python篇(深浅拷贝、常用模块、内置函数)

    深浅拷贝 有时候,尤其是当你在处理可变对象时,你可能想要复制一个对象,然后对其做出一些改变而不希望影响原来的对象.这就是Python的copy所发挥作用的地方. 定义了当对你的类的实例调用copy.c ...

随机推荐

  1. C++ list运用实例

    C++ list运用实例 #include <list> #include <iostream> #include <algorithm> #include < ...

  2. Ajax验证

    import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactor ...

  3. Linux终端复制粘贴后前后会多出0~和~1

    在终端中执行即可 printf "\e[?2004l" 在终端无法复制问题 set mouse=r

  4. EasyDSS高性能RTMP、HLS(m3u8)、HTTP-FLV、RTSP流媒体服务器软件二次开发接口对接说明示列

    EasyDSS相关功能 EasyDSS流媒体服务器软件,提供一站式的转码.点播.直播.时移回放服务,极大地简化了开发和集成的工作.其中,点播版本主要包含:上传.转码.分发.直播版本主要包含:直播.录像 ...

  5. DL Practice:Cifar 10分类

    Step 1:数据加载和处理 一般使用深度学习框架会经过下面几个流程: 模型定义(包括损失函数的选择)——>数据处理和加载——>训练(可能包括训练过程可视化)——>测试 所以自己写代 ...

  6. CMDBuild部署教程

    一.CMDBuild简介 CMDBuild是一个通过Web界面配置的CMDB系统.可以通过Web界面来进行建模.创建资产数据库,并处理相关的工作流程.CMDBuild可用于集中管理数据库模块和外部应用 ...

  7. spring boot2X整合Consul一服务注册与发现

    Consul 是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置. 关键特性: 服务注册/发现 数据强一致性保证 多数据中心 健康检查 key/value存储 1.下载 htt ...

  8. SPI ServiceLoader源码分析

    public class ddd { public static void main(String[] args) { ServiceLoader1<Hello> sl = Service ...

  9. 基于Livy的Spark提交平台搭建与开发

    为了方便使用Spark的同学提交任务以及加强任务管理等原因,经调研采用Livy比较靠谱,下图大致罗列一下几种提交平台的差别. 本文会以基于mac的单机环境搭建一套Spark+Livy+Hadoop来展 ...

  10. Linux内核--伙伴系统--页释放

    本文转载自:http://www.cnblogs.com/tolimit/ 感觉原博分析的不错,借花献佛. ---------------------------------------------- ...