私有属性是将变量作为私有的来使用:
- 单下划线私有属性,其要求只有类本身和子类自己能访问到这些变量
- 双下划线私有属性,其要求只有类本身能访问、子类不能访问
- 通过以下方式可以在外部调用私有属性
1、单下划线与双下划线外部调用区别
单下划线私有属性可在外部通过实例直接调用,双下滑线私有属性可在外部通过【_类名__私有属性名】调用
import time, traceback
class People1:
province = '河北'
_city = "保定"
__county = '曲阳'
def __init__(self, name, age, gender):
self.name = name
self._age = age
self.__gender = gender
def info(self):
print("这是实例方法")
print('%s 是类属性' % self.province)
print('%s 是私有类属性1' % self._city)
print('%s 是私有类属性2' % self.__county)
print('%s 是实例属性' % self.name)
print('%s 是私有实例属性1' % self._age)
print('%s 是私有实例属性2' % self.__gender)
def test1():
print('验证1:私有属性的单下划线与双下划线,在外部调用时区别')
person1 = People1("Mary", '18', '女')
print("单下划线外部调用结果:%s" % person1._age)
try:
time.sleep(1)
print(person1.__gender)
except Exception as e:
print("双下划线直接调用异常:")
traceback.print_exc()
time.sleep(1)
print("双下划线正确外部调用方式(_类名__私有属性名):%s" % person1._People1__gender)
print("该实例所有属性与方法:%s" % dir(person1))
test1()
验证1:私有属性的单下划线与双下划线,在外部调用时区别
单下划线外部调用结果:18
双下划线直接调用异常:
Traceback (most recent call last):
File "/Users/yxt/Desktop/MyProjects/OsTest/test4.py", line 31, in test1
print(person1.__gender)
AttributeError: 'People1' object has no attribute '__gender'
双下划线正确外部调用方式(_类名__私有属性名):女
该实例所有属性与方法:['_People1__county', '_People1__gender', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_age', '_city', 'info', 'name', 'province']
2、父类与子类的双下划线私有属性外部调用时区别
父类双下划线私有属性通过【_父类名__私有属性名】调用;
子类双下划线私有属性通过【_子类名__私有属性名】调用,
class Man(People1):
def __init__(self, name, age, gender, phone):
super(Man, self).__init__(name, age, gender)
self._age = '100'
self.__phone = phone
def func(self):
print('func')
def test2():
print('验证2:父类的双下划线私有属性与子类的双下划线私有属性,在调用时区别')
man = Man('john', '40', '男', '13633088809')
print("父类的双下划线私有属性调用方式(_父类名__私有属性名):%s" % man._People1__gender)
print("子类的双下划线私有属性调用方式(_子类名__私有属性名):%s" % man._Man__phone)
test2()
验证2:父类的双下划线私有属性与子类的双下划线私有属性,在调用时区别
父类的双下划线私有属性调用方式(_父类名__私有属性名):男
子类的双下划线私有属性调用方式(_子类名__私有属性名):13633088809
3、super方法继承父类,验证生成属性与方法的顺序
super方法继承父类,验证生成属性与方法的顺序
class Woman(People1):
def __init__(self, name, age, gender, phone):
print('生成实例,包含父类的类属性,父类与子类的函数:')
print(dir(self))
print('绑定父类的实例属性:')
super(Woman, self).__init__(name, age, gender) # 继承父类
print(dir(self))
print('绑定子类的实例属性')
self.phone = phone
print(dir(self))
def func(self):
print('func')
def test3():
print('验证3:super方法继承父类(super在定义子类实例属性之前),验证生成属性的顺序')
woman = Woman('Kate', '50', '女', '15010689376')
test3()
验证3:super方法继承父类(super在定义子类实例属性之前),验证生成属性的顺序
生成实例,包含父类的类属性,父类与子类的函数:
['_People1__county', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_city', 'func', 'info', 'province']
绑定父类的实例属性:
['_People1__county', '_People1__gender', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_age', '_city', 'func', 'info', 'name', 'province']
绑定子类的实例属性
['_People1__county', '_People1__gender', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_age', '_city', 'func', 'info', 'name', 'phone', 'province']
4、类属性、私有属性的内存存储
类属性与实例属性区别:类属性在内存只有一个,即类作为对象只初始化一次;实例属性在内存有多个,即每个实例都有对应的实例属性
def test4():
print('验证4:在创建类时生成类属性,在创建实例时生成实例属性')
person1 = People1("Mary", '18', '女')
person2 = People1("Jack", '16', '男')
print("%s 与 %s 对比:类属性【省份】内存地址【%s】、实例属性【姓名】内存地址【%s】" % (
person1.name, person2.name, "相等" if id(person1.province) == id(person2.province) else "不相等", "相等" if id(person1.name) == id(person2.name) else "不相等"))
test4()
验证4:在创建类时生成类属性,在创建实例时生成实例属性
Mary 与 Jack 对比:类属性【省份】内存地址【相等】、实例属性【姓名】内存地址【不相等】