今天首席CTO笔记来给各位分享关于python一个对象有多少个属性的相关内容,其中也会对python对象的三个特性进行详细介绍,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录一览:
1、python对象是什么概念?2、python类的属性有哪几种?如何访问它们?3、python 如何根据一个对象的属性值查询该对象其他某个属性值?4、python定义一个学生类,包含三个属性5、Python对象6、Python 查看对象属性的几种方式: __dict__, dir(), vars(), locals()python对象是什么概念?
所说所有的变量都是对象。 对象在python里,其实是一个指针,指向一个数据结构,数据结构里有属性,有方法。\x0d\x0a \x0d\x0a对象通常就是指变量。从面向对象OO的概念来讲,对象是类的一个实例。在python里很简单,对象就是变量。\x0d\x0a \x0d\x0aclass A:\x0d\x0a myname="class a"\x0d\x0a上面就是一个类。不是对象\x0d\x0aa=A()\x0d\x0a这里变量a就是一个对象。\x0d\x0a它有一个属性(类属性),myname,你可以显示出来\x0d\x0aprint a.myname\x0d\x0a \x0d\x0a所以,你看到一个变量后面跟点一个小数点。那么小数点后面就是它的属性或者是方法。带括号的方法。不带就是属性。
python类的属性有哪几种?如何访问它们?
属性的访问机制
一般情况下,属性访问的默认行为是从对象的字典中获取,并当获取不到时会沿着一定的查找链进行查找。例如 a.x 的查找链就是,从 a.__dict__['x'] ,然后是 type(a).__dict__['x'] ,再通过 type(a) 的基类开始查找。
若查找链都获取不到属性,则抛出 AttributeError 异常。
一、__getattr__ 方法
这个方法是当对象的属性不存在是调用。如果通过正常的机制能找到对象属性的话,不会调用 __getattr__ 方法。
class A:
a = 1
def __getattr__(self, item):
print('__getattr__ call')
return item
t = A()
print(t.a)
print(t.b)
# output
1
__getattr__ call
b
二、__getattribute__ 方法
这个方法会被无条件调用。不管属性存不存在。如果类中还定义了 __getattr__ ,则不会调用 __getattr__()方法,除非在 __getattribute__ 方法中显示调用__getattr__() 或者抛出了 AttributeError 。
class A:
a = 1
def __getattribute__(self, item):
print('__getattribute__ call')
raise AttributeError
def __getattr__(self, item):
print('__getattr__ call')
return item
t = A()
print(t.a)
print(t.b)
所以一般情况下,为了保留 __getattr__ 的作用,__getattribute__() 方法中一般返回父类的同名方法:
def __getattribute__(self, item):
return object.__getattribute__(self, item)
使用基类的方法来获取属性能避免在方法中出现无限递归的情况。
三、__get__ 方法
这个方法比较简单说明,它与前面的关系不大。
如果一个类中定义了 __get__(), __set__() 或 __delete__() 中的任何方法。则这个类的对象称为描述符。
class Descri(object):
def __get__(self, obj, type=None):
print("call get")
def __set__(self, obj, value):
print("call set")
class A(object):
x = Descri()
a = A()
a.__dict__['x'] = 1 # 不会调用 __get__
a.x # 调用 __get__
如果查找的属性是在描述符对象中,则这个描述符会覆盖上文说的属性访问机制,体现在查找链的不同,而这个行文也会因为调用的不同而稍有不一样:
如果调用是对象实例(题目中的调用方式),a.x 则转换为调用:。type(a).__dict__['x'].__get__(a, type(a))
如果调用的是类属性, A.x 则转换为:A.__dict__['x'].__get__(None, A)
其他情况见文末参考资料的文档
四、__getitem__ 方法
这个调用也属于无条件调用,这点与 __getattribute__ 一致。区别在于 __getitem__ 让类实例允许 [] 运算,可以这样理解:
__getattribute__适用于所有.运算符;
__getitem__适用于所有 [] 运算符。
class A(object):
a = 1
def __getitem__(self, item):
print('__getitem__ call')
return item
t = A()
print(t['a'])
print(t['b'])
如果仅仅想要对象能够通过 [] 获取对象属性可以简单的:
def __getitem(self, item):
return object.__getattribute__(self, item)
总结
当这几个方法同时出现可能就会扰乱你了。我在网上看到一份示例还不错,稍微改了下:
class C(object):
a = 'abc'
def __getattribute__(self, *args, **kwargs):
print("__getattribute__() is called")
return object.__getattribute__(self, *args, **kwargs)
# return "haha"
def __getattr__(self, name):
print("__getattr__() is called ")
return name + " from getattr"
def __get__(self, instance, owner):
print("__get__() is called", instance, owner)
return self
def __getitem__(self, item):
print('__getitem__ call')
return object.__getattribute__(self, item)
def foo(self, x):
print(x)
class C2(object):
d = C()
if __name__ == '__main__':
c = C()
c2 = C2()
print(c.a)
print(c.zzzzzzzz)
c2.d
print(c2.d.a)
print(c['a'])
可以结合输出慢慢理解,这里还没涉及继承关系呢。总之,每个以 __get 为前缀的方法都是获取对象内部数据的钩子,名称不一样,用途也存在较大的差异,只有在实践中理解它们,才能真正掌握它们的用法。
python 如何根据一个对象的属性值查询该对象其他某个属性值?
在 Chrom 类中新增一个类函数,遍历存储列表并返回匹配的对象
大概写了个样例
运行结果
python定义一个学生类,包含三个属性
class student():
# 构造函数
# 对当前对象的实例的初始化
def __init__(self, name, age, score):
self.name = name
self.age = age
self.score = score
# isinstance函数判断一个对象是否是一个已知的类型,类似type
def get_name(self):
if isinstance(self.name, str):
return self.name
def get_age(self):
if isinstance(self.age, int):
return self.age
def get_course(self):
a = max(self.score)
if isinstance(a, int):
return a
zm = student('zhangming', 20, [69, 88, 100])
print(zm.get_name())
print(zm.get_age())
print(zm.get_course())
Python对象
众所周知,Python是一门面向对象的语言,在Python无论是数值、字符串、函数亦或是类型、类,都是对象。
对象是在 堆 上分配的结构,我们定义的所有变量、函数等,都存储于堆内存,而变量名、函数名则是一个存储于 栈 中、指向堆中具体结构的引用。
要想深入学习Python,首先需要知道Python对象的定义。
我们通常说的Python都是指CPython,底层由C语言实现,源码地址: cpython [GitHub]
Python对象的定义位于 Include/object.h ,是一个名为 PyObject 的结构体:
Python中的所有对象都继承自PyObejct,PyObject包含一个用于垃圾回收的双向链表,一个引用计数变量 ob_refcnt 和 一个类型对象指针 ob_type
从PyObejct的注释中,我们可以看到这样一句:每个指向 可变大小Python对象 的指针也可以转换为 PyVarObject* (可变大小的Python对象会在下文中解释)。 PyVarObejct 就是在PyObject的基础上多了一个 ob_size 字段,用于存储元素个数:
在PyObject结构中,还有一个类型对象指针 ob_type ,用于表示Python对象是什么类型,定义Python对象类型的是一个 PyTypeObject 接口体
实际定义是位于 Include/cpython/object.h 的 _typeobject :
在这个类型对象中,不仅包含了对象的类型,还包含了如分配内存大小、对象标准操作等信息,主要分为:
以Python中的 int类型 为例,int类型对象的定义如下:
从PyObject的定义中我们知道,每个对象的 ob_type 都要指向一个具体的类型对象,比如一个数值型对象 100 ,它的ob_type会指向 int类型对象PyLong_Type 。
PyTypeObject结构体第一行是一个PyObject_VAR_HEAD宏,查看宏定义可知PyTypeObject是一个变长对象
也就是说,归根结底 类型对象也是一个对象 ,也有ob_type属性,那 PyLong_Type 的 ob_type 是什么呢?
回到PyLong_Type的定义,第一行 PyVarObject_HEAD_INIT(PyType_Type, 0) ,查看对应的宏定义
由以上关系可以知道, PyVarObject_HEAD_INIT(PyType_Type, 0) = { { _PyObject_EXTRA_INIT 1, PyType_Type } 0} ,将其代入 PyObject_VAR_HEAD ,得到一个变长对象:
这样看就很明确了,PyLong_Type的类型就是PyType_Typ,同理可知, Python类型对象的类型就是PyType_Type ,而 PyType_Type对象的类型是它本身
从上述内容中,我们知道了对象和对象类型的定义,那么根据定义,对象可以有以下两种分类
Python对象定义有 PyObject 和 PyVarObject ,因此,根据对象大小是否可变的区别,Python对象可以划分为 可变对象(变长对象) 和 不可变对象(定长对象)
原本的对象a大小并没有改变,只是s引用的对象改变了。这里的对象a、对象b就是定长对象
可以看到,变量l仍然指向对象a,只是对象a的内容发生了改变,数据量变大了。这里的对象a就是变长对象
由于存在以上特性,所以使用这两种对象还会带来一种区别:
声明 s2 = s ,修改s的值: s = 'new string' ,s2的值不会一起改变,因为只是s指向了一个新的对象,s2指向的旧对象的值并没有发生改变
声明 l2 = l ,修改l的值: l.append(6) ,此时l2的值会一起改变,因为l和l2指向的是同一个对象,而该对象的内容被l修改了
此外,对于 字符串 对象,Python还有一套内存复用机制,如果两个字符串变量值相同,那它们将共用同一个对象:
对于 数值型 对象,Python会默认创建0~2 8 以内的整数对象,也就是 0 ~ 256 之间的数值对象是共用的:
按照Python数据类型,对象可分为以下几类:
Python创建对象有两种方式,泛型API和和类型相关的API
这类API通常以 PyObject_xxx 的形式命名,可以应用在任意Python对象上,如:
使用 PyObjecg_New 创建一个数值型对象:
这类API通常只能作用于一种类型的对象上,如:
使用 PyLong_FromLong 创建一个数值型对象:
在我们使用Python声明变量的时候,并不需要为变量指派类型,在给变量赋值的时候,可以赋值任意类型数据,如:
从Python对象的定义我们已经可以知晓造成这个特点的原因了,Python创建对象时,会分配内存进行初始化,然后Python内部通过 PyObject* 变量来维护这个对象,所以在Python内部各函数直接传递的都是一种泛型指针 PyObject* ,这个指针所指向的对象类型是不固定的,只能通过所指对象的 ob_type 属性动态进行判断,而Python正是通过 ob_type 实现了多态机制
Python在管理维护对象时,通过引用计数来判断内存中的对象是否需要被销毁,Python中所有事物都是对象,所有对象都有引用计数 ob_refcnt 。
当一个对象的引用计数减少到0之后,Python将会释放该对象所占用的内存和系统资源。
但这并不意味着最终一定会释放内存空间,因为频繁申请释放内存会大大降低Python的执行效率,因此Python中采用了内存对象池的技术,是的对象释放的空间会还给内存池,而不是直接释放,后续需要申请空间时,优先从内存对象池中获取。
Python 查看对象属性的几种方式: __dict__, dir(), vars(), locals()
为了方便用户查看类中包含哪些属性,Python 类提供了 __dict__ 属性。需要注意的一点是,该属性可以用类名或者类的实例对象来调用,用类名直接调用 __dict__ ,会输出该由类中所有类属性组成的字典;而使用类的实例对象调用 __dict__ ,会输出由类中所有实例属性组成的字典。
先来看一下Python类的 __dict__ 属性和类实例对象的 __dict__ 属性,例子如下:
从以上的测试结果中可以得出以下结论:
看几个小例子:
如果没传入参数,就打印当前调用位置的属性和属性值,类似于下面的 locals() 。
locals() 返回调用者当前局部名称空间的字典。在一个函数内部,局部名称空间代表在函数执行时候定义的所有名字, locals() 函数返回的就是包含这些名称的字典。
结语:以上就是首席CTO笔记为大家整理的关于python一个对象有多少个属性的全部内容了,感谢您花时间阅读本站内容,希望对您有所帮助,更多关于python对象的三个特性、python一个对象有多少个属性的相关内容别忘了在本站进行查找喔。