美文网首页
Python对象属性管理

Python对象属性管理

作者: 郭_扬 | 来源:发表于2019-06-15 16:42 被阅读0次
  • _dict_
  • _slots_
  • 属性管理
    hasattr()函数
    getattr()函数
    setattr()函数
    delattr()函数

Python下一切皆对象,每个对象都有多个属性(attribute),Python对属性有一套统一的管理方案。dict是用来存储对象属性的一个字典,其键为属性名,值为属性的值。

_dict_

class Spring(object):
    #season 为类的属性
    season = "the spring of class"

>>> Spring.__dict__
mappingproxy({'__module__': '__main__', 'season': 'the spring of class', '__dict__': <attribute '__dict__' of 'Spring' objects>, '__weakref__': <attribute '__weakref__' of 'Spring' objects>, '__doc__': None})

>>> Spring.__dict__['season']
'the spring of class'
>>> Spring.season
'the spring of class'

Spring._dict_['season']就是访问类属性,同时通过.号也可以访问该类属性

# 类实例化
s = Spring()
>>>s.__dict__
{}

实例属性的dict是空的,因为season是属于类属性

>>> s.season
'the spring of class'

s.season是指向了类属性中Spring.season

#建立实例对象
>>> s.season = 'the spring of instance'
>>> s.__dict__
{'season': 'the spring of instance'}

这样实例属性里面就不空了,这时候建立的s.season属性与上面s.season(类属性)重名,并且把原来的“遮盖了”。

#查看类属性
>>> Spring.season
'the spring of class'
>>> Spring.__dict__['season']
'the spring of class'

由上我们看到Spring类season属性并没有受到实例影响,其原因是实例s对象建立时s.season未初始化则会自动指向类属性,如果实例属性被修改那么就不指向类属性,同时类属性也不会受到影响

#定义其它实例属性
>>> s = Spring()
>>> s.lang = 'python'
>>> Spring.lang
Traceback (most recent call last):
  File "<pyshell#9>", line 1, in <module>
    Spring.lang
AttributeError: type object 'Spring' has no attribute 'lang'

上明错误表面 实例对象添加内容,不是类属性

#定义一个类
>>> class Spring:
    def tree(self,x):
        self.x = x
        print(self.x)

>>> Spring.__dict__['tree']
<function Spring.tree at 0x036E4AE0>

在类属性是存在tree方法

>>> s.__dict__['tree']
Traceback (most recent call last):
  File "<pyshell#33>", line 1, in <module>
    s.__dict__['tree']
KeyError: 'tree'

但是实例对象sdict 方法里不存在tree方法

>>> s.tree('123')
123

但是s能调用tree方法,其原因是s.tree指向了Spring.tree方法。 实例s与self新建了对应关系,两者是一个外一个内,在方法中self.x = x 。 将x值赋给了self.x,也就是实例应该拥有这么一个属性。self相当于java中this指针。

>>> s.__dict__
{'x': '123'}

即实例方法(s.tree('123'))的第一个参数(self,但没有写出来)绑定实例s,透过self.x来设定值,给s.dict添加属性值

换一个角度来看

class Spring:
    def tree(self,x):
        print(x)

这个方法没有self.x = x 直接输出x

>>> s = Spring()
>>> s.tree('123')
123
>>> s.__dict__
{}

再看一个例子

class Person(object):                      
    name = 'python'                        
    age = 18                               

    def __init__(self):                    
        self.sex = 'boy'                   
        self.like = 'papapa'               

    @staticmethod                          
    def stat_func():                       
        print 'this is stat_func'          

    @classmethod                           
    def class_func(cls):                   
        print 'class_func'                 


person = Person()                          
print 'Person.__dict__: ', Person.__dict__ 
print 'person.__dict__: ', person.__dict__

运行结果:

Person.__dict__:  {'__module__': '__main__', 'name': 'python', '__init__': <function __init__ at 0x000000000385B518>, 'class_func': <classmethod object at 0x0000000003847F78>, '__dict__': <attribute '__dict__' of 'Person' objects>, 'age': 18, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None, 'stat_func': <staticmethod object at 0x00000000037CFAF8>}
person.__dict__:  {'like': 'papapa', 'sex': 'boy'}

由此可见, 类的普通方法、类方法、静态方法、全局变量以及一些内置的属性都是放在类对象dict里

而实例对象中存储了一些self.xxx的一些东西

在类的继承中,子类有自己的dict, 父类也有自己的dict,子类的全局变量和方法放在子类的dict中,父类的放在父类dict中。

class Person(object):                          
    name = 'python'                            
    age = 18                                   

    def __init__(self):                        
        self.sex = 'boy'                       
        self.like = 'papapa'                   

    @staticmethod                              
    def stat_func():                           
        print 'this is stat_func'              

    @classmethod                               
    def class_func(cls):                       
        print 'class_func'                     


class Hero(Person):                            
    name = 'super man'                         
    age = 1000                                 

    def __init__(self):                        
        super(Hero, self).__init__()           
        self.is_good = 'yes'                   
        self.power = 'fly'                     


person = Person()                              
print 'Person.__dict__: ', Person.__dict__     
print 'person.__dict__: ', person.__dict__     

hero = Hero()                                  
print 'Hero.__dict__: ', Hero.__dict__         
print 'hero.__dict__: ', hero.__dict__

运行结果:

Person.__dict__:  {'__module__': '__main__', 'name': 'python', '__init__': <function __init__ at 0x000000000374B518>, 'class_func': <classmethod object at 0x0000000003750048>, '__dict__': <attribute '__dict__' of 'Person' objects>, 'age': 18, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None, 'stat_func': <staticmethod object at 0x0000000003737FD8>}
person.__dict__:  {'like': 'papapa', 'sex': 'boy'}
Hero.__dict__:  {'age': 1000, '__doc__': None, '__module__': '__main__', '__init__': <function __init__ at 0x000000000374B668>, 'name': 'super man'}
hero.__dict__:  {'is_good': 'yes', 'like': 'papapa', 'power': 'fly', 'sex': 'boy'}

从运行结果可以看出,类对象的dict虽然没有继承父类的,但是实例对象继承了父类的实例属性

_slots_

现在我们终于明白了,动态语言与静态语言的不同

  • 动态语言:可以在运行的过程中,修改代码

  • 静态语言:编译时已经确定好代码,运行过程中不能修改

如果我们想要限制实例的属性怎么办?比如,只允许对Person实例添加name和age属性。

为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的slots变量,来限制该class实例能添加的属性:

class Person:
    __slots__ = ("name", "age")
    def __init__(self,name,age):
        self.name = name
        self.age = age

p = Person("老王",20)
p.score = 100

输出

Traceback (most recent call last):
  File "C:/Users/Administrator/PycharmProjects/test/app.py", line 8, in <module>
    p.score = 100
AttributeError: 'Person' object has no attribute 'score'

注意: 使用slots要注意,slots定义的属性仅对当前类实例起作用,对继承的子类是不起作用的

class Person:
    __slots__ = ("name", "age")
    def __init__(self,name,age):
        self.name = name
        self.age = age

class GoodPerson(Person):
    pass

p = GoodPerson("老王",20)
p.score = 100

当你定义 slots 后,Python就会为实例使用一种更加紧凑的内部表示。 实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个字典。所以slots是创建大量对象时节省内存的方法。slots的副作用是作为一个封装工具来防止用户给实例增加新的属性。 尽管使用slots可以达到这样的目的,但是这个并不是它的初衷。

属性管理

hasattr()函数

hasattr()函数用于判断对象是否包含对应的属性

语法:

  hasattr(object,name)

参数:

  object--对象

  name--字符串,属性名

返回值:

  如果对象有该属性返回True,否则返回False

示例:

class People:
    country='China'
    def __init__(self,name):
        self.name=name

    def people_info(self):
        print('%s is xxx' %(self.name))

obj=People('aaa')

print(hasattr(People,'country'))
#返回值:True
print('country' in People.__dict__)
#返回值:True
print(hasattr(obj,'people_info'))
#返回值:True
print(People.__dict__)
##{'__module__': '__main__', 'country': 'China', '__init__': <function People.__init__ at 0x1006d5620>, 'people_info': <function People.people_info at 0x10205d1e0>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}

1.3.2. getattr()函数

描述:

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

语法:

  getattr(object,name,default)

参数:

  object--对象

  name--字符串,对象属性

  default--默认返回值,如果不提供该参数,在没有对于属性时,将触发AttributeError。

返回值:

  返回对象属性值
class People:
    country='China'
    def __init__(self,name):
        self.name=name

    def people_info(self):
        print('%s is xxx' %(self.name))

obj=getattr(People,'country')
print(obj)
#返回值China
#obj=getattr(People,'countryaaaaaa')
#print(obj)
#报错
# File "/getattr()函数.py", line 32, in <module>
#     obj=getattr(People,'countryaaaaaa')
# AttributeError: type object 'People' has no attribute 'countryaaaaaa'
obj=getattr(People,'countryaaaaaa',None)
print(obj)
#返回值None

1.3.3. setattr()函数

描述:

  setattr函数,用于设置属性值,该属性必须存在

语法:

  setattr(object,name,value)

 参数:

  object--对象

  name--字符串,对象属性

  value--属性值

返回值:

  无
class People:
    country='China'
    def __init__(self,name):
        self.name=name

    def people_info(self):
        print('%s is xxx' %(self.name))

obj=People('aaa')

setattr(People,'x',111) #等同于People.x=111
print(People.x)

#obj.age=18
setattr(obj,'age',18)
print(obj.__dict__)
#{'name': 'aaa', 'age': 18}
print(People.__dict__)
#{'__module__': '__main__', 'country': 'China', '__init__': <function People.__init__ at 0x1007d5620>, 'people_info': <function People.people_info at 0x10215d1e0>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None, 'x': 111}

1.3.4. delattr()函数

描述:

  delattr函数用于删除属性

  delattr(x,'foobar)相当于del x.foobar

语法:

  setattr(object,name)

参数:

  object--对象

  name--必须是对象的属性

返回值:

  无

示例:

class People:
    country='China'
    def __init__(self,name):
        self.name=name

    def people_info(self):
        print('%s is xxx' %(self.name))

delattr(People,'country') #等同于del People.country
print(People.__dict__)
{'__module__': '__main__', '__init__': <function People.__init__ at 0x1006d5620>, 'people_info': <function People.people_info at 0x10073d1e0>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}
补充示例

class Foo:
    def run(self):
        while True:
            cmd=input('cmd>>: ').strip()
            if hasattr(self,cmd):
                func=getattr(self,cmd)
                func()

    def download(self):
        print('download....')

    def upload(self):
        print('upload...')

# obj=Foo()
# obj.run()

相关文章

  • Python高级第四天

    对象属性管理 Python下一切皆对象,每个对象都有多个属性(attribute),Python对属性有一套统一的...

  • Python对象属性管理

    _dict_ _slots_ 属性管理hasattr()函数getattr()函数setattr()函数delat...

  • python基础-02

    Python 面向对象 python是一门面向对象的语言 Python内置类属性 python对象销毁(垃圾回收)...

  • 对象属性的增删改查

    python中对象的属性支持增删改查 属性的增删改查 1.查(获取对象属性) 对象.属性 - 获取指定对象指定属...

  • python中的标准类型

    python使用对象来存储数据,类型是每个对象都有的属性,准确地说,所有的python对象都有三个属性:身份,类型...

  • 类和模块的特殊属性和方法

    Python一切皆对象(object),每个对象都可能有多个属性(attribute)。Python的属性有一套统...

  • 常用类、实例内置属性

    Python下一切皆对象,每个对象一般都有多个属性(attribute)。同样每个Python类会带有内置属性(包...

  • Python 函数的属性

    Python的函数也是对象,所以它也具有对象共有的属性: 除了这些与对象共有的属性之外。函数还具有自己特有的属性:...

  • Python 属性访问机制

    简介 Python 中,一切皆对象。 当我们访问某个对象属性时,在不同的情况下,Python 对属性的访问机制有所...

  • Python学习-面向对象

    查看所有Python相关学习笔记 面向对象 面向对象知识点汇总: 面向对象静态属性实例属性(self)静态方法(@...

网友评论

      本文标题:Python对象属性管理

      本文链接:https://www.haomeiwen.com/subject/vsvbfctx.html