Python里面的私有属性也是个伪私有属性,没有真正的私有化。
私有属性在官方文档里是这样说的:定义一个公用的接口。公用的接口里面的类属性是一个下划线或者两个下划线开头的,那么这些属性被视为私有属性。
私有属性就是说:这个接口是公有的,如果你要用我这个类里面的私有属性,可以用。但是如果我把私有属性修改了,我就不会通知你。
就是说,给你建议:只要用下划线标识了,我这个属性只在类里面用,你不要在外面用,你在外面用了也可以。但是开发者在类里面改了私有属性,他不会告诉你。你的代码在外面调用了这个属性,他在这个类里面把属性改掉了,你的代码就直接报错了。
类属性可以通过类和实例对象去访问。单下划线开头的私有属性是可以访问的。
双下划线开头的私有属性,对外不能直接访问。 提示没有__attr3
这个属性,因为它被改了个名字。
class Test:
attr1=1000 #公有属性
#私有属性
_attr2=3000
__attr3=4000
c = Test()
#类属性可以通过类和实例对象去访问。
#这个是公有属性。
# print(Test.attr1)#通过类去访问。
# print(c.attr1)#通过实例对象去访问。
#单下划线开头的私有属性。
# print(Test._attr2)
# print(c._attr2)
#双下划线开头的私有属性。
# 双下划线开头的私有属性,对外不能直接访问。
print(Test.__attr3)
运行结果
双下划线开头的私有属性,对外不能直接访问,为了保护这个变量。(对外改了一个名字)
类也是一个对象。创建一个对象的时候,Python会自动给对象添加一个__dict__
的属性。这个里面包含了这个对象所有的属性值。
所有的属性会以键值对存在里面。那么看看Test这个类里面的属性:
class Test:
attr1=1000 #公有属性
#私有属性
_attr2=3000
__attr3=4000
c = Test()
#类属性可以通过类和实例对象去访问。
#这个是公有属性。
# print(Test.attr1)#通过类去访问。
# print(c.attr1)#通过实例对象去访问。
#单下划线开头的私有属性。
# print(Test._attr2)
# print(c._attr2)
#双下划线开头的私有属性。
# 双下划线开头的私有属性,对外不能直接访问,为了保护这个变量。(对外改了一个名字)
# print(Test.__attr3)
print(Test.__dict__)
运行结果
在原有的属性名前面加了一个_类名
。
把代码改成:print(Test._Test__attr3)
class Test:
attr1=1000 #公有属性
#私有属性
_attr2=3000
__attr3=4000
c = Test()
#类属性可以通过类和实例对象去访问。
#这个是公有属性。
# print(Test.attr1)#通过类去访问。
# print(c.attr1)#通过实例对象去访问。
#单下划线开头的私有属性。
# print(Test._attr2)
# print(c._attr2)
#双下划线开头的私有属性。
# 双下划线开头的私有属性,对外不能直接访问,为了保护这个变量。(对外改了一个名字)
# 在原有的属性名前面加了一个_类名
print(Test._Test__attr3)
# print(Test.__dict__)
运行结果
之前写的单例模式:用的是个公有属性instance=None
。当时重写个new方法实现了单例模式。
我现在在创建对象之后,在外面改了属性值。通过MyTest.instance=None
把它的值改成None,在下面又可以创建新的对象了。现在判断条件又不会成立,它又会创建对象了。
class MyTest(object):
instance=None
def __new__(cls, *args, **kwargs):
if not cls.instance:
cls.instance=object.__new__(cls)
return cls.instance
else:
return cls.instance
t1=MyTest()
t1.name="QingHan"
MyTest.instance=None
为了单例模式更安全一点,在这里选择用私有属性。 代码改成这样:
class MyTest(object):
__instance=None
def __new__(cls, *args, **kwargs):
if not cls.__instance:
cls.__instance=object.__new__(cls)
return cls.__instance
else:
return cls.__instance
t1=MyTest()
t1.name="QingHan"
以后定义单例模式的时候,记住这个地方用私有属性:
定义私有属性后,就不能直接改了。虽然它也是可以改的,既然声明了是私有属性,别人就不会去改。
通过类和实例对象都能访问私有属性。 单下划线开头的,对外是公开的,在外面可以直接访问。
双下划线开头的,为了保护这个对象,对外访问的话,改了个名字。
对外面改了个名字:在原有的属性名前面加了一个_类名
。
继承可以继承父类的属性和方法。
通过代码看下:
class Test:
attr1=1000 #公有属性
#私有属性
_attr2=3000
__attr3=4000
# c = Test()
#类属性可以通过类和实例对象去访问。
#这个是公有属性。
# print(Test.attr1)#通过类去访问。
# print(c.attr1)#通过实例对象去访问。
#单下划线开头的私有属性。
# print(Test._attr2)
# print(c._attr2)
#双下划线开头的私有属性。
# 双下划线开头的私有属性,对外不能直接访问,为了保护这个变量。(对外改了一个名字)
# 在原有的属性名前面加了一个_类名。
# print(Test._Test__attr3)
# print(c._Test__attr3)
# print(Test.__dict__)
#私有属性的继承问题
class A(Test):
pass
a=A()
print(a.attr1)
print(a._attr2)
print(a._Test__attr3)
#可以继承
运行结果
__dict__
是个魔法属性。这个属性就是我们创建一个对象的时候,它会自动给这个对象添加一个__dict__
属性。
因为__dict__
属性的存在,如果我们定义一个类,因为__dict__
的存在,它会造成内存的消耗。
通过__dict__
来看类所用的属性。这个A类里面没有定义任何一个类属性,自动添加了2个属性在里面, 父类的属性没有过来:
class Test:
attr1=1000 #公有属性
#私有属性
_attr2=3000
__attr3=4000
# c = Test()
#类属性可以通过类和实例对象去访问。
#这个是公有属性。
# print(Test.attr1)#通过类去访问。
# print(c.attr1)#通过实例对象去访问。
#单下划线开头的私有属性。
# print(Test._attr2)
# print(c._attr2)
#双下划线开头的私有属性。
# 双下划线开头的私有属性,对外不能直接访问,为了保护这个变量。(对外改了一个名字)
# 在原有的属性名前面加了一个_类名。
# print(Test._Test__attr3)
# print(c._Test__attr3)
# print(Test.__dict__)
#私有属性的继承问题
class A(Test):
pass
a=A()
#可以继承。
print(a.attr1)
print(a._attr2)
print(a._Test__attr3)
print(A.__dict__)
运行结果
加上这句代码print(Test.__dict__)
。
这个是父类的属性:
父类定义了属性,多了好多东西。
在A类里面定义属性:
class Test:
attr1=1000 #公有属性
#私有属性
_attr2=3000
__attr3=4000
# c = Test()
#类属性可以通过类和实例对象去访问。
#这个是公有属性。
# print(Test.attr1)#通过类去访问。
# print(c.attr1)#通过实例对象去访问。
#单下划线开头的私有属性。
# print(Test._attr2)
# print(c._attr2)
#双下划线开头的私有属性。
# 双下划线开头的私有属性,对外不能直接访问,为了保护这个变量。(对外改了一个名字)
# 在原有的属性名前面加了一个_类名。
# print(Test._Test__attr3)
# print(c._Test__attr3)
# print(Test.__dict__)
#私有属性的继承问题
class A(Test):
name="QingHan"
__name="mmmm"
a=A()
#可以继承。
print(a.attr1)
print(a._attr2)
print(a._Test__attr3)
print(Test.__dict__)
print(A.__dict__)
运行结果
子类继承父类的时候没有__dict__
和__weakref__
这2个东西。
class Test:
attr1=1000 #公有属性
#私有属性
_attr2=3000
__attr3=4000
# c = Test()
#类属性可以通过类和实例对象去访问。
#这个是公有属性。
# print(Test.attr1)#通过类去访问。
# print(c.attr1)#通过实例对象去访问。
#单下划线开头的私有属性。
# print(Test._attr2)
# print(c._attr2)
#双下划线开头的私有属性。
# 双下划线开头的私有属性,对外不能直接访问,为了保护这个变量。(对外改了一个名字)
# 在原有的属性名前面加了一个_类名。
# print(Test._Test__attr3)
# print(c._Test__attr3)
# print(Test.__dict__)
#私有属性的继承问题
class A:
name="QingHan"
__name="mmmm"
a=A()
#可以继承。
# print(a.attr1)
# print(a._attr2)
# print(a._Test__attr3)
print(Test.__dict__)
print(A.__dict__)
不是继承的话,会多出这2个东西:
运行结果
多出这2个东西,会消耗内存。
如果通过继承的方式定义类,父类已经有__dict__
和__weakref__
属性了,所以子类不会再有这两个属性了,可以节省内存。
如果定义一个类只创建一个对象,这个对象会给你绑定一个__dict__
属性。那么__dict__
里面存了一些数据。
如果这个类创建了特别多的对象,每个对象都会有一个__dict__
属性。
这个时候,__dict__
属性会占用特别多的内存空间。
class A():
def a(self):
print("洗衣服")
def b(self):
print("吃饭")
haier=A()
haier.a()
qinghan=A()
qinghan.b()
print(A.__dict__)
运行结果
除标明“图片来自网络”的图片,其它文章中的图片皆为本人所画,计算机知识都一样,如有雷同,纯属巧合。