鱼C论坛

 找回密码
 立即注册
查看: 2657|回复: 13

[知识点备忘] 第064讲:类和对象(VII)

[复制链接]
发表于 2022-6-17 04:40:03 | 显示全部楼层 |阅读模式
购买主题 已有 25 人购买  本主题需向作者支付 5 鱼币 才能浏览
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-9-4 15:48:00 | 显示全部楼层
class C:
    def __init__(self,x):
        self.__x=x
    def set_x(self,x):
        self.__x=x
    def get_x(self):
        print(self.__x)

        
c=C(250)
c.__x
Traceback (most recent call last):
  File "<pyshell#249>", line 1, in <module>
    c.__x
AttributeError: 'C' object has no attribute '__x'
c.get_x()
250
c.set_x(520)
c.get_x()
520
c.__dict__
{'_C__x': 520}
c._C__x
520
class D:
    def __func(self):
        print("hello fishc.")

        
d=D()
d.__func()
Traceback (most recent call last):
  File "<pyshell#260>", line 1, in <module>
    d.__func()
AttributeError: 'D' object has no attribute '__func'. Did you mean: '_D__func'?
d._D__func()
hello fishc.
c.__y=250
c.__dict__
{'_C__x': 520, '__y': 250}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-9-4 16:22:23 | 显示全部楼层
class C:
    def __init__(self,x):
        self.x=x

        
c=C(250)
c.x
250
c.__dict__
{'x': 250}
c.y=520
c.__dict__
{'x': 250, 'y': 520}
c.__dict__['z']=666
c.__dict__
{'x': 250, 'y': 520, 'z': 666}
c.z
666
class C:
    __slots__=["x","y"]
    def __init__(self,x):
        self.x=x

        
c=C(250)
c.x
250
c.y=520
c.y
520
c.z=666
Traceback (most recent call last):
  File "<pyshell#287>", line 1, in <module>
    c.z=666
AttributeError: 'C' object has no attribute 'z'
class D:
    __slots__=["x","y"]
    def __init__(self,x,y,z):
        self.x=x
        self.y=y
        self.z=z

        
d=D(3,4,5)
Traceback (most recent call last):
  File "<pyshell#295>", line 1, in <module>
    d=D(3,4,5)
  File "<pyshell#294>", line 6, in __init__
    self.z=z
AttributeError: 'D' object has no attribute 'z'
class E(C):
    pass

e=E(250)
e.x
250
e.y=520
e.y
520
e.z=666
e.__slots__
['x', 'y']
e.__dict__
{'z': 666}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-9-28 11:18:21 | 显示全部楼层
私有变量是一种保护机制,指通过某种手段,使得对象中的属性或方法无法被外部所访问。Python引入的“name mangling”(名字改编、名称改写或名称修饰)机制可以实现“私有化”,只要在变量名前加上两个连续的下横线即可实现,方法名也与之类似。然而,Python其实是将该变量或方法偷换了名字,以此来掩人耳目;__dict__属性可以揭开真相,我们仍可通过“下横线+类名+私有变量名”或“下横线+类名+私有方法名”的方式访问到该变量或方法,只不过在现实中并不提倡这么做,毕竟这会违背私有化的初衷。事实上,Python给予程序员最大的自由度,并不存在仅限从对象内部访问的私有变量。此外,名字改编仅发生在类实例化对象时,实例化对象后添加的属性并不会被改编。
通常来说,单个下横线开头的变量是仅供内部使用的变量,尽量不要随意访问或修改;单个下横线结尾的变量可用于解决命名冲突(如与Python关键字重名)的问题,这是约定俗成的规则。
由于Python动态添加属性背后的实现原理是字典,以空间换时间,会牺牲大量的内存空间,因此,当我们不需要动态添加属性的功能时,便可以使用__slots__属性来避免利用字典造成的空间浪费。我们只需将必要的属性放入列表赋值给__slots__,这样对象就会划分一个固定大小的空间来存放指定的属性,省去了为__dict__属性划分的字典,有时可以大幅减少内存消耗,不失为一个好方法!继承自父类的__slots__属性是不会在子类中生效的,该子类仍可动态添加属性(拥有__dict__字典),因为Python只关注各个具体的类中定义的__slots__属性。虽然使用__slots__属性会牺牲Python动态语言的灵活性,但利用这一副作用又可以限制类属性的滥用,由此可见:技术永远是中立的,因地制宜,对症下药,方能实现最佳疗效!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 2 反对 0

使用道具 举报

发表于 2023-1-2 23:06:39 | 显示全部楼层
本帖最后由 Ensoleile 于 2023-1-10 00:36 编辑

私有变量和__slots__()
#私有变量:P147 Name Mangling,
# 定义方法:__变量名,外部访问方法:_类名__变量名

#舍得之道:对象中灵活添加的属性,是用字典存储,字典效率快的背后是占用了大量内存(空间换时间)
class C:
    def __init__(self, x):
        self.x = x

c = C(250)
print(c.__dict__)
#{'x': 250}
c.__dict__['y'] = 520
print(c.__dict__)
#{'x': 250, 'y': 520}

#__slots__:如果已经明确一个类的对象设计出来不会有动态添加属性的需求,可以使用__slots__的类属性避免利用字典存放造成空间浪费
class D:
    __slots__ = ['x', 'y'] #列表中的就是希望的属性名
    def __init__(self, x):
        self.x = x

d = D(10)
d.y = 20
print(d.x, d.y, sep='   ')
try:
    print(d.__dict__)
except AttributeError as e:
    print(e)
#'D' object has no attribute '__dict__'
try:
    d.z = 66
except AttributeError as e:
    print(e)
#'D' object has no attribute 'z'

#类的内部同样不允许创建__slots__不包含的属性
class D:
    __slots__ = ['x', 'y']
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z
# d = D(3, 4, 5)
#AttributeError: 'D' object has no attribute 'z'
#使用__slots__后,对象就会划分一个固定大小的空间来存放指定属性
#__slots__限制动态添加属性,也可以用来防止属性的滥用

#继承在父类的__slots__属性不会在子类中生效
class E(C):
    pass

e = E(3)
e.z = 10
print(e.__dict__)
#{'x': 3, 'z': 10}
print(e.__slots__)
#AttributeError: 'E' object has no attribute '__slots__'
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 2 反对 0

使用道具 举报

发表于 2023-1-13 11:43:24 | 显示全部楼层
Ensoleile 发表于 2023-1-2 23:06
私有变量和__slots__()

感谢,以后我也要边学边记笔记然后发评论区

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-2-1 11:37:44 | 显示全部楼层
子类继承__solts__的属性,不会对新加属性造成影响
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-2-7 15:16:14 | 显示全部楼层
class C:
    def __init__(self,x):
        self.__x = x
    def set_x(self,x):
        self.__x = x
    def get_x(self):
        print(self.__x)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-2-17 17:48:22 | 显示全部楼层
get私有变量
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-2-21 16:55:37 | 显示全部楼层
下节课没知识备忘了,也没作业了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-30 16:12:05 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-4-26 23:04:34 | 显示全部楼层
懂了,就像电算时代之前,银行不乐意给个人储户开活期储存,以缩限每个账户(存折)属性量,进而大大减小人工操作和局端存底成本。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-1-22 14:14:42 | 显示全部楼层
在线等,求教:一个函数中如何添加多个私有变量啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-7-19 09:21:00 | 显示全部楼层
leizhenzi23 发表于 2024-1-22 14:14
在线等,求教:一个函数中如何添加多个私有变量啊

请问你是说这样子吗
class A:
    def __init__(self,x,y):
        self.__x=x
        self.__y=y
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-23 19:16

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表