阅读前请看一下:我是一个热衷于记录的人,每次写博客会反复研读,尽量不断提升博客质量。文章设置为仅粉丝可见,是因为写博客确实花了不少精力。希望互相进步谢谢!!
文章目录
- 阅读前请看一下:我是一个热衷于记录的人,每次写博客会反复研读,尽量不断提升博客质量。文章设置为仅粉丝可见,是因为写博客确实花了不少精力。希望互相进步谢谢!!
- 前言
- 一、笔记
- 1、type()、isinstance()、dir()、hasattr()、getattr()、setattr()共性?
- 2、isinstance() 与 type() 区别:
- 3、types模块:
- 4、dir():
- 5、hasattr()、getattr()、setattr():
- 6、定义类时属性、参数值傻傻分不清楚?
- 7、定义类时,初始化函数定义的不同,导致实例化对象的方式也不同
- 8、object和instance的关系:MyObject.run、MyObject().run、MyObject.run()、MyObject().run()四者区别
- 8、创建实例时一定定义变量进行引用,否则无法对后续进行操作
前言
time:2022/06/10
记录学习python的笔记 ,有知识点,也有评论区的精华,还有自己的一些疑问。
具体文章见:https://www.liaoxuefeng.com/wiki/1016959663602400/1017499532944768?t=1654821830104#0
提示:以下是本篇文章正文内容
一、笔记
1、type()、isinstance()、dir()、hasattr()、getattr()、setattr()共性?
答:都是针对类实例化后的对象
而言,是为了搞清楚对象的一些特性。故第一个参数永远是实例化后的对象
,而非类。
2、isinstance() 与 type() 区别:
-
type() 不会认为子类是一种父类类型,
不考虑继承关系
。 -
isinstance() 会认为子类是一种父类类型,
考虑继承关系
。 -
如果要判断两个类型是否相同
推荐使用 isinstance()
。#继承关系:Animal-->Dog print(type(dog) == Animal) #False,因为不考虑继承 print(type(dog) == Dog) #True print(isinstance(dog, Animal)) #True,因为考虑继承 print(isinstance(dog, Dog)) #True
-
使用isinstance还可以判断一个变量是否为某些类型中的一种,如下代码:
print(isinstance([1, 2, 3], (list, tuple))) #Output: True isinstance((1, 2, 3), (list, tuple)) #Output: True
3、types模块:
- 用途:判断一个对象是否为函数。
- 使用:
import types def fn(): pass print(type(fn)==types.FunctionType) #输出:True print(type(abs)==types.BuiltinFunctionType) #输出:True print(type(lambda x: x)==types.LambdaType) #输出:True print(type((x for x in range(1, 10))) == types.GeneratorType) #输出:True
4、dir():
-
用途:返回一个list,里面包含了该对象的所有属性与方法
-
使用:
print(dir('Abc')) #Output: ['__add__', '__class__',..., '__subclasshook__', 'capitalize', 'casefold',..., 'zfill']
上面代码说明:类似__xxx__的属性和方法在Python中都是有特殊用途的,比如__len__方法返回长度。在Python中,如果你调用len()函数试图获取一个对象的长度,实际上,在len()函数内部,它自动去调用该对象的__len__()方法,所以,下面的代码是等价的:
print(len('ABC')) #Output: 3 print('ABC'.__len__()) #Output: 3
剩下的都是普通属性或方法,比如lower()返回小写的字符串:
print('ABC'.lower()) #output: 'abc'
5、hasattr()、getattr()、setattr():
-
用途:
- hasattr(object, name)判断一个对象里面是否有name属性或者name方法。
- getattr(obj,name[,default)函数用于返回一个对象属性值
- setattr(obj,name,value)函数对应函数getattr(),用于设置属性值,该属性不一定是存在的。
-
这三个函数仍然是外部程序对实例对象的属性的调用,故不可用来处理私有变量
-
相对于object.attribution的直接调用,上诉函数的优点在于第二个参数除了是字符串外(
既可以是属性名,又可以是方法名,但一定注意一定要加‘’
),还可以当作变量,具体见如下代码:#把dict的key - value复制到obj,前提是obj有对应得property def dict2bean(obj, d): for k, v in items(d): if hasattr(obj, k): setattr(obj, k, v) # 能写成obj.k = v吗?
那里一定不能写成obj.k = v
。例如setattr(obj,‘y’,19) 中的‘y’,此时并不是一个变量,它只是一个字符串,起着匹配的作用;而代码中setattr(obj, k, v)的k虽然也是匹配作用,但此时并非一个简单的字符串,而是一个变量,指向每次循环对应的dic中的key值,若写成obj.k = v这个,obj中就会生成k这个属性,故不行。 -
只有在不知道对象信息的时候我们才去获取对象信。
如果可以直接写:sum = obj.x + obj.y
就不要写:
sum = getattr(obj, 'x') + getattr(obj, 'y')
一个正确的用法的例子如下:
def readImage(fp): if hasattr(fp, 'read'): return readData(fp) return None
假设我们希望从文件流fp中读取图像,我们首先要判断该fp对象是否存在read方法,如果存在,则该对象是一个流,如果不存在,则无法读取。hasattr()就派上了用场。
请注意,在Python这类动态语言中,根据鸭子类型,有read()方法,不代表该fp对象就是一个文件流,它也可能是网络流,也可能是内存中的一个字节流,但只要read()方法返回的是有效的图像数据,就不影响读取图像的功能。
6、定义类时属性、参数值傻傻分不清楚?
- 如下代码中:aa,bb才是对象的属性,name,score只是参数,是用来传值的。
class myobject(): def __init__(self, name, score): self.aa = name self.bb = score
- 只是我们习惯这样写,参数名和属性名相同,若要定义为私有属性,在属性前加两个下划线,代码如下:
class myobject(): def __init__(self, name, score): self.name = name #公有属性:name self.__score = score #私有属性:__score ```-
7、定义类时,初始化函数定义的不同,导致实例化对象的方式也不同
-
第一种含self以外参数的初始化函数,定义如下:
class MyObject(object): def __init__(self, name, score): self.name = name self.__score = score test = MyObject('Michael', 100) #print(test.name, test.__score) #错误写法,__score为私有属性,外接无法访问,故报错 print(test.name) #Output: Michael test.name = 'Bob' #修改名字后覆盖,注意__score为私有属性,不能外部修改 print(test.name) #Output: Bob
由于初始化函数含有name、__score两个参数,故初始化时需要传入两个参数。
-
第二种只含self参数的初始化函数,定义如下:
class MyObject(object): def __init__(self): self.name = 'Michael' #这里一定要初始化,否则报错 self.__score = 100 #这里一定要初始化,否则报错 #test = MyObject('Michael', 100) #错误写法,由于初始化只有self参数,故不能传参 test = MyObject() #print(test.name, test.__score) #错误写法,__score为私有属性,外接无法访问,故报错 print(test.name) #Output: Michael test.name = 'Bob' #修改名字后仍然覆盖,注意__score为私有属性,不能外部修改 print(test.name) #Output: Bob
-
总结:初始化函数若有其他参数,创建实例时就必须传参;否则就不用
8、object和instance的关系:MyObject.run、MyObject().run、MyObject.run()、MyObject().run()四者区别
- 示例代码如下:
class MyObject(object):
def __init__(self):
self.name = 'Michael' #这里一定要初始化,否则报错
self.__score = 100 #这里一定要初始化,否则报错
def run(self):
print('I am running')
print(type(MyObject.run))
#Output: <class 'function'>
print(type(MyObject().run))
#Output: <class 'method'>
print(type(MyObject.run()))
#报错TypeError,因为run函数定义时有self,self会指向实例,故会报缺少参数的错误,故此时需要先创建实例以后才能调用
print(type(MyObject().run()))
#Output: I am running
# <class 'NoneType'>
```
- 分析上述代码:
-
MyObject.run是function,MyObject().run是method。method与实例关联,调用时会把实例作为参数隐式传递,function不会;
-
MyObject.run()报错,原因见代码注释
-
MyObject().run()是运行实例中的run函数,故首先会打印“I am running”,其次由于没有return语句,故默认返回None,故类型也是“NoneType”;
-
永远记住,类只是一个模板,模板是不会亲自下海干活的。
首先区分函数本身和函数调用:python中如果不加括号,除了个别的,那就是函数本身(即函数名、即标识符(你可以理解为变量)),加了括号代表函数调用(即运行前面的东西)。例如内置绝对值函数,abs是函数本身,是函数名,也是一个变量,它指向了函数体这个对象(即定义的数据规则),而abs()是调用执行函数并返回一个值。
例如单独看MyObject就是一个类名,是一个变量,指向了一个类对象,程序员可以通过MyObjcet去进行操作,而不再是通过地址去操作;再单独看MyObject()是调用这个类创建一个实例(官方解释“如何创建实例?类名+()”也印证了)。
再单独看run,就是函数本身,是一个函数名,是一个变量,指向了函数对象;而单独看run()就是调用函数。那为何MyObject.run和MyObject().run会返回function和method两种类型呢?
其实method可以看作是function的一个特例。method指的是对象的关联函数,即必须是针对于创建的实例而言,故必须实例化后才能调用!而function这里指的是类中的函数,再想想最初学面向过程时定义的一般的函数,其类型也是function。
故MyObject().run()就很好理解了,前面代表创建一个实例,才能下海干活,后面代表调用这个实例中的run函数。
-
写到这,应该有人会问了,上面代码中,属性都是通过self.xxx定义的,类里面的函数第一个参数也永远是self,可不可以不用self呢?关于这个问题,请看,类属性与实例属性。
-
8、创建实例时一定定义变量进行引用,否则无法对后续进行操作
直接看下面代码:
class MyObject(object):
def __init__(self):
self.x = 9 #默认为9
def power(self):
return self.x * self.x
def set_x(self, x):
self.x = x
#MyObject()就是实例,在没有变量引用MyObject()的情况下,后续的操作(赋值等)其实都没有用
print(MyObject().x) #结果不变,为9
MyObject().x = 2
print(MyObject().x) #结果不变,为9
setattr(MyObject(), 'x', 2)
print(MyObject().x) #结果不变,为9
MyObject().set_x(2)
print(MyObject().x) #结果不变,为9
print("_____________________________________________")#分割线
#obj=MyObject()就把实例引用给到变量obj,用变量obj可以操作实例,变量obj的值就是实例地址
obj = MyObject() #实例化
print(obj.x) #默认为9
obj.x = 2
print(obj.x) #结果变化为2
setattr(obj, 'x', 9)
print(obj.x) #结果变化为9
obj.set_x(2)
print(obj.x) #结果变化为2
码字不易,谢谢点赞!!!
码字不易,谢谢点赞!!!
码字不易,谢谢点赞!!!