类与实例的属性及增删改查

类的属性有两种:数据属性和函数属性

类的数据属性是所对象共享的

类的函数属性是绑定给对象用的

下面分别来看一下,什么是数据属性,什么是函数属性,先简单定义一个类:

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

    def play_ball(self,ball):
        print('%s 正在打 %s' %(self.name))

通过调用__dict__,会返回一个字典,这个字典就是属性字典:

print(Chinese.__dict__)
>>> {'__module__': '__main__', 'country': 'China', '__init__': <function Chinese.__init__ at 0x000002085EB7B6A8>, 'play_ball': <function Chinese.play_ball at 0x000002085EB7B730>, '__dict__': <attribute '__dict__' of 'Chinese' objects>, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, '__doc__': None}

可以看到,country、__init__、play_ball都是字典里面的key,其中country就是数据属性,另外两个就是函数属性,如果要查看类的某个属性,操作如下:

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

    def play_ball(self,ball):
        print('%s 正在打 %s' %(self.name))


#查看
print(Chinese.country)

>>>China

直接返回就是属性对应的值,也就是说,类名加上.,本质上就是在查看属性字典,返回的就是key对应的value,如果要修改这个属性,操作如下:

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

    def play_ball(self,ball):
        print('%s 正在打 %s' %(self.name))

Chinese.country='Japan'
print(Chinese.country)

>>> Japan

给对应的属性赋值,就是在修改这一属性,和字典的操作十分相似,所以增加和删除的属性的操作也是类似的:

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

    def play_ball(self,ball):
        print('%s 正在打 %s' %(self.name))

Chinese.race='黄种人'
print(Chinese.race)
print(Chinese.__dict__)

>>> 黄种人
>>>{'__module__': '__main__', 'country': 'China', '__init__': <function Chinese.__init__ at 0x000002BCBDF1B6A8>, 'play_ball': <function Chinese.play_ball at 0x000002BCBDF1B730>, '__dict__': <attribute '__dict__' of 'Chinese' objects>, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, '__doc__': None, 'race': '黄种人'}

del Chinese.race
print(Chinese.__dict__)

>>>{'__module__': '__main__', 'country': 'China', '__init__': <function Chinese.__init__ at 0x0000025123EEB6A8>, 'play_ball': <function Chinese.play_ball at 0x0000025123EEB730>, '__dict__': <attribute '__dict__' of 'Chinese' objects>, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, '__doc__': None}

通过查看属性字典,可以看到增删的属性变化。那么实例的属性是怎样的呢?

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

    def play_ball(self,ball):
        print('%s 正在打 %s' %(self.name,ball))

p1=Chinese('pengfy')
print(p1.__dict__)
print(p1.country)
p1.play_ball('basketball)

>>>{'name': 'pengfy'}
>>>China
>>>pengfy 正在打 basketball

首先,我们看到实例的属性字典里面只有一个属性,就是实例化过程中执行类的__init__方法产生的一个name属性,那为什么还能调用其他属性?如下图:

obj.name会先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常 ,这个可以理解成函数的作用域中查找参数的情况。那么实例属性的增删改查和类一样,操作如下:

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

    def play_ball(self,ball):
        print('%s 正在打 %s' %(self.name,ball))
p1=Chinese('alex')
print(p1.__dict__)

# 查看
print(p1.name)
print(p1.play_ball)

#增加
p1.age=18
print(p1.__dict__)
print(p1.age)

# 不要修改底层的属性字典
p1.__dict__['sex']='male'
# print(p1.__dict__)
# print(p1.sex)

# 修改
p1.age=19
print(p1.__dict__)
print(p1.age)

#删除
del p1.age
print(p1.__dict__)

现在再来看开始说的两句话:类的数据属性是所对象共享的,类的函数属性是绑定给对象用的

 

#类的数据属性是所有对象共享的,id都一样
print(id(Chinese.country))
print(id(p1.country))
print(id(p2.country))
print(id(p3.country))

'''
1807264015728
1807264015728
1807264015728
1807264015728
'''



#类的函数属性是绑定给对象使用的,obj.method称为绑定方法,内存地址都不一样
#ps:id是python的实现机制,并不能真实反映内存地址,如果有内存地址,还是以内存地址为准
print(Chinese.play_ball)
print(p1.play_ball)
print(p2.play_ball)
print(p3.play_ball)
'''
<function Chinese.play_ball at 0x000001A4CB1BB730>
<bound method Chinese.play_ball of <__main__.Chinese object at 0x000001A4CB1DEF98>>
<bound method Chinese.play_ball of <__main__.Chinese object at 0x000001A4CB1E6198>>
<bound method Chinese.play_ball of <__main__.Chinese object at 0x000001A4CB1E64A8>>

 

posted @ 2019-04-03 12:07 彭方炎QAQ 阅读(...) 评论(...) 编辑 收藏