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. postgre with递归查询组织路径

    with递归查询组织路径 SELECT r.id, (array_to_string( array( select name from ( with recursive rec as( select ...

  2. Docker容器部署Mysql数据库服务器

    本节会用到的Docker命令如下: docker images 查看mysql镜像id docker run -d -p xxxxxxxxxxxxxxx/zhufc/mysql:v2 通过镜像生成 启 ...

  3. CSS布局:sticky定位

    stick定位一如其名:它随“正常”文档流而动,直到规定位置,尔后“粘”在那里:或者,当它发现自己可以跟随“正常”文档流而脱离sticky位置时,就果断离开从而加入文档流. 代码与效果如下: < ...

  4. Centos7环境下部署搭建discuz论坛

    1.首先搭建lnmp环境 2.从官网复制git地址(https://gitee.com/ComsenzDiscuz/DiscuzX),在服务器上安装git命令 yum install git -y  ...

  5. python:字符串中提取特定的数据

    在日志文件中有一大堆,格式相同的文本,需要提取出接口耗时的时间 >>> 运单号:71742507538566,快递100接口耗时:8,返回结果:[{"lengthPre&q ...

  6. 【MongoDB学习之五】Java中使用MongoDB

    环境 MongoDB 3.0 CentOS6.5_x64 相关jar:mongo-java-driver-3.0.0.jar package com.mongodb; import java.util ...

  7. Postgres-XL集群ERROR :Failed to get pooled connections原因说明

    集群说明 6台服务器.其中1台(rt67-1)运行GTM,其余5台均运行1个GTM_PROXY.1个Coordinator node.3个Data node.每个服务器连接到3组网络中,每个Data ...

  8. .Net Core 3 骚操作 之 用 Windows 桌面应用开发 Asp.Net Core 网站

    前言 曾经在开发 Asp.Net 网站时就在想,为什么一定要把网站挂到 IIS 上?网站项目的 Main 函数哪儿去了?后来才知道这个 Main 函数在 w3wp.exe 里,这也是 IIS 的主进程 ...

  9. 【springcloud】【idea】启动服务报错Command line is too long. Shorten command line for XXXApplication or also for Spring Boot default configuration.

    在workspace.xml 在标签<component name="PropertiesComponent">里 添加<property name=" ...

  10. 在CAD中插入谷歌地球卫星地图

    本文主要介绍如何在CAD中插入谷歌地球卫星地图,作为参照光栅图像.谷歌地球卫星地图使用“迈高图-地图数据下载器”(以下简称:迈高图)下载.迈高图会给出相关插入参数(插入点和缩放比例),保证插入卫星地图 ...