【python】详解类class的属性:类数据属性、实例数据属性、特殊的类属性、属性隐藏(二)

自上一篇python中的类,对象,方法,属性初认识(一)认识了类的基本架构,下面继续对类进行详解,更加深入了解类的属性、方法、访问控制这三个方面的类容。

紧接上一篇类的实例:

class person():
	tall = 180
    def __init__(self,name,age,weight):
        self.name = name
        self.age = age
        self.weight = weight
    def infoma(self):
        print('%s is %s weights %s'%(self.name,self.age,self.__weight))


person = person('bruce',25,60)
infoma = person.infoma()

一、数据属性

1、在上面的person类中,“tall”、“name”、"age"和"weight "都被称为类的数据属性,但是它们又分为类数据属性和实例数据属性。

首先看一段代码,代码中分别展示了对类数据属性和实例数据属性的访问:

class person(object):
    tall = 180
    hobbies = []
    def __init__(self, name, age,weight):
        self.name = name
        self.age = age
        self.weight = weight
    def infoma(self):
        print('%s is %s weights %s'%(self.name,self.age,self.weight))
person.hobbies.extend(["football", "woman"])   #类数据属性属于类本身,可以通过类名进行访问/修改,此处添加"football"、"woman"两个
print("person hobbies list: %s" %person.hobbies   ) 
# class can add class attribute after class defination
person.hobbies2 = ["reading", "jogging", "swimming"]  #在类定义之后,可以通过类名动态添加类数据属性,新增的类属性也被类和所有实例共有
print( "person hobbies2 list: %s" %person.hobbies2  )  
print( dir(person))


Bruce = person("Bruce", 25,60)    #实例数据属性只能通过实例访问
print ("%s is %d years old" %(Bruce.name, Bruce.age)   )
# class instance can add new attribute 
# "gender" is the instance attribute only belongs to wilber
Bruce.gender = "male"   #在实例生成后,还可以动态添加实例数据属性,但是这些实例数据属性只属于该实例
print( "%s is %s" %(Bruce.name, Bruce.gender) )  
# class instance can access class attribute
print( dir(Bruce))
Bruce.hobbies.append("C#")
print (Bruce.hobbies)


will = person("Will", 27,60) 
print( "%s is %d years old" %(will.name, will.age) )  
# will shares the same class attribute with wilber
# will don't have the "gender" attribute that belongs to wilber
print( dir(will) )    
print (will.hobbies)

通过内建函数dir(),或者访问类的字典属性’_ _dict _ _'这两种方式都可以查看类有哪些属性,代码的输出为:

person hobbies list: ['football', 'woman']   #类数据属性属于类本身,可以通过类名进行访问/修改
person hobbies2 list: ['reading', 'jogging', 'swimming']
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'hobbies', 'hobbies2', 'infoma', 'tall']
Bruce is 25 years old  #实例数据属性只能通过实例访问
Bruce is male #实例数据属性只能通过实例访问
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'gender', 'hobbies', 'hobbies2', 'infoma', 'name', 'tall', 'weight']
['football', 'woman', 'C#']
Will is 27 years old
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'hobbies', 'hobbies2', 'infoma', 'name', 'tall', 'weight']
['football', 'woman', 'C#']

对于类数据属性和实例数据属性,可以总结为:

  • 类数据属性属于类本身,可以通过类名进行访问/修改
  • 类数据属性也可以被类的所有实例访问/修改
  • 在类定义之后,可以通过类名动态添加类数据属性,新增的类属性也被类和所有实例共有
  • 实例数据属性只能通过实例访问
  • 在实例生成后,还可以动态添加实例数据属性,但是这些实例数据属性只属于该实例

2、特殊的类属性:对于所有的类,都有一组特殊的属性

  • _ _ name_ _:类的名字(字符串)
  • _ _ doc _ _ :类的文档字符串
  • _ _ bases _ _:类的所有父类组成的元组
  • _ _ dict _ _:类的属性组成的字典
  • _ _ module _ _:类所属的模块
  • _ _ class _ _:类对象的类型
class person(object):
    tall = 180
    hobbies = []
    def __init__(self, name, age,weight):
        self.name = name
        self.age = age
        self.weight = weight
    def infoma(self):
        print('%s is %s weights %s'%(self.name,self.age,self.weight))

print(person.__name__)
print(person.__doc__)
print(person.__bases__)
print(person.__dir__)
print(person.__module__)
print(person.__class__)

输出结果为:

person
None
(<class 'object'>,)
<method '__dir__' of 'object' objects>
__main__
<class 'type'>

3、属性隐藏:类数据属性属于类本身,被所有该类的实例共享;并且,通过实例可以去访问/修改类属性。但是,在通过实例中访问类属性的时候一定要谨慎,因为可能出现属性"隐藏"的情况。

Bruce = person("Bruce", 25,180)

print("person.tall is Bruce.tall: ", person.tall is Bruce.tall)
Bruce.tall = 185    #重新赋值或者修改
print( "person.tall is Bruce.tall: ", person.tall is Bruce.tall)
print( person.__dict__)
print( Bruce.__dict__)
del Bruce.tall   #再次删除实例的赋值
print("person.tall is Bruce.tall: ", person.tall is Bruce.tall)  #person.tall is Bruce.tall为True


Bruce.tall += 3    
print("person.tall is Bruce.tall: ", person.tall is Bruce.tall)
print(person.__dict__)
print(Bruce.__dict__)


del Bruce.tall

print("person.hobbies is Bruce.hobbies: ", person.hobbies is Bruce.hobbies)
Bruce.hobbies = ["C#", "Python"]
print ("person.hobbies is Bruce.hobbies : ", person.hobbies is Bruce.hobbies)
print( person.__dict__)
print( Bruce.__dict__)
del Bruce.hobbies
print( "person.hobbies is Bruce.hobbies: ", person.hobbies is Bruce.hobbies)

print() 

Bruce.hobbies.append("CSS")
print("person.hobbies is Bruce.hobbies: ", person.hobbies is Bruce.hobbies)
print(person.__dict__)
print(Bruce.__dict__)

输出结果:

person.tall is Bruce.tall:  True
person.tall is Bruce.tall:  False
{'tall': 180, 'infoma': <function person.infoma at 0x000001C9B9D0D6A8>, '__dict__': <attribute '__dict__' of 'person' objects>, '__module__': '__main__', '__init__': <function person.__init__ at 0x000001C9B9D0DE18>, '__weakref__': <attribute '__weakref__' of 'person' objects>, 'hobbies': [], '__doc__': None}
{'weight': 180, 'name': 'Bruce', 'tall': 185, 'age': 25}
person.tall is Bruce.tall:  True
person.tall is Bruce.tall:  False
{'tall': 180, 'infoma': <function person.infoma at 0x000001C9B9D0D6A8>, '__dict__': <attribute '__dict__' of 'person' objects>, '__module__': '__main__', '__init__': <function person.__init__ at 0x000001C9B9D0DE18>, '__weakref__': <attribute '__weakref__' of 'person' objects>, 'hobbies': [], '__doc__': None}
{'weight': 180, 'name': 'Bruce', 'tall': 183, 'age': 25}
person.hobbies is Bruce.hobbies:  True

person.hobbies is Bruce.hobbies:  False
{'tall': 180, 'infoma': <function person.infoma at 0x000001C9B9D0D6A8>, '__dict__': <attribute '__dict__' of 'person' objects>, '__module__': '__main__', '__init__': <function person.__init__ at 0x000001C9B9D0DE18>, '__weakref__': <attribute '__weakref__' of 'person' objects>, 'hobbies': [], '__doc__': None}
{'weight': 180, 'name': 'Bruce', 'hobbies': ['C#', 'Python'], 'age': 25}
person.hobbies is Bruce.hobbies :  True

person.hobbies is Bruce.hobbies:  True
{'tall': 180, 'infoma': <function person.infoma at 0x000001C9B9D0D6A8>, '__dict__': <attribute '__dict__' of 'person' objects>, '__module__': '__main__', '__init__': <function person.__init__ at 0x000001C9B9D0DE18>, '__weakref__': <attribute '__weakref__' of 'person' objects>, 'hobbies': ['CSS'], '__doc__': None}
{'weight': 180, 'name': 'Bruce', 'age': 25}

对于不可变类型的类属性,隐藏属性可以总结为:

  • 对于不可变类型的类属性person.tall,可以通过实例Bruce进行访问,并且"person.tall is Bruce.tall"

  • 当通过实例赋值/修改tall属性的时候将为实例Bruce新建一个tall实例属性,这时,“person.tall is not Bruce.tall”

  • 当通过"del Bruce.tall"语句删除实例的tall属性后,再次成为"person.tall is Bruce.tall"

对于可变类型的类属性,隐藏属性可以总结为:

  • 同样对于可变类型的类属性person.hobbies,可以通过实例Bruce进行访问,并且"person.hobbies is
    Bruce. hobbies"
  • 当通过实例赋值hobbies 属性的时候,都将为实例Bruce新建一个hobbies实例属性,这时,“person.hobbies is not
    Bruce. hobbies”
  • 当通过"del Bruce. hobbies"语句删除实例的hobbies属性后,再次成为"person. hobbies is Bruce.
    hobbies"
  • 当通过实例修改hobbies属性的时候,将修改Bruce. hobbies指向的内存地址(即person.hobbies),此时,“person.hobbies is not Bruce. hobbies”

注意,虽然通过实例可以访问类属性,但是,不建议这么做,最好还是通过类名来访问类属性,从而避免属性隐藏带来的不必要麻烦

  • 25
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
### 回答1: 在 Python 中,私有属性是指在内部使用两个下划线前缀来声明的属性。这些属性不能在的外部直接访问,只能在的内部使用。 这种声明方式的目的是为了让的使用者不能随意修改内部的状态,从而保证的正常运行。 例如: ``` class MyClass: def __init__(self): self.__private_attribute = 0 def get_attribute(self): return self.__private_attribute def set_attribute(self, value): self.__private_attribute = value ``` 在上面的代码中,`__private_attribute` 是一个私有属性,不能在的外部直接访问。要访问或者修改这个属性,必须通过提供的 `get_attribute` 和 `set_attribute` 方法。 注意,在 Python 中,私有属性并不是真正意义上的私有,它仍然可以通过 `_ClassName__attribute_name` 的方式在外部访问。但是这种方式并不建议使用,而是应该通过提供的公共方法来访问和修改的内部状态。 ### 回答2: Python中的私有属性是指以双下划线"__"开头的属性,例如"__name"。私有属性的特点是只能在的内部访问,无法通过实例对象直接访问。 Python的私有属性主要有以下几个特点: 1. 访问限制:私有属性只能在的内部进行访问,无法在的外部通过实例对象直接访问。这种限制可以保护属性的安全性,防止外部的错误操作。 2. 名字重整:Python解释器会对私有属性的名字进行重整,将"__name"重命名为"_名__name"。这种重命名的机制是为了在一定程度上绕过访问限制,但不建议直接访问重整后的名字。 3. 编程习惯:私有属性的使用主要是为了约定俗成的编程习惯,用来表示属性是私有的,不应该被外部访问。但实际上,Python并没有严格的访问控制机制,只要知道私有属性的名字,还是可以直接进行访问。 4. getter和setter方法:由于私有属性无法直接访问,所以一般通过定义getter和setter方法来对私有属性进行读取和修改。getter方法用于获取私有属性的值,setter方法用于设置私有属性的值。通过这种方式,可以间接地访问和修改私有属性。 总结来说,Python的私有属性主要是一种约定俗成的编程习惯,用以表示属性是私有的,不应该被外部直接访问。虽然Python并没有严格的访问控制机制,但通过使用私有属性、重整和getter/setter方法等方式,可以在一定程度上实现对私有属性的访问限制和保护。 ### 回答3: Python中的私有属性是指以双下划线“__”开头的属性,它们只能在的内部访问,无法在的外部直接访问和修改。这种机制是为了保护属性,避免外部代码对属性的意外修改和访问。 私有属性可以在的内部使用,包括在的方法和其他属性中。在方法中,可以通过self.__属性名来访问私有属性。私有属性与普通属性的访问方式是一样的,没有特殊的语法或操作。 私有属性的主要作用是封装数据,控制属性的可见性和保护数据安全。通过将属性设置为私有,可以防止外部代码直接访问和修改属性的值,只能通过提供的方法来操作属性。这样做可以有效控制数据的有效性和一致性。 另外,私有属性也可以用于避免命名冲突。以双下划线开头的属性会自动在属性名前面添加一个名前缀,这样可以在继承关系中避免同名属性的冲突。当子定义了与父同名的私有属性时,它们实际上是不同的属性。 需要注意的是,虽然私有属性无法直接访问,但Python并没有严格限制访问私有属性。实际上,通过使用“_名__属性名”的方式,仍然可以访问到私有属性。但这种操作是不被推荐的,因为它违背了的封装原则,容易导致代码的混乱和不稳定。 总之,私有属性Python中是一种可以实现封装和数据安全的机制。通过将属性设置为私有,可以有效地保护属性的访问和修改,控制数据的有效性和一致性。同时,私有属性还可以用于避免命名冲突,提高代码的可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值