这篇博客记录廖雪峰python教程的习题(四)

这篇博客探讨了Python中获取对象信息的方法,包括isinstance和hasattr的使用,以及如何操作实例属性和类属性。文章通过代码示例讲解了在类中使用slots优化内存效率,并介绍了@property装饰器实现属性的getter和setter方法,提供可控的属性操作。此外,博主还提到在编写示例时遇到的问题并进行了修正,最后提出了一道关于使用@property为Screen对象添加属性的作业题。
摘要由CSDN通过智能技术生成

获取对象信息

主要是需要掌握 isinstance的用法,以及 hasattr(对象,属性) getattr(对象,属性) hasattr(对象,属性)
贴一段代码,解释其用法:

class My_Object(object):
    def __init__(self):
        self.x=9    #就是这个类有一个属性x 并且把该属性的值设为9 之前都是可以用户输入属性的值
    def calc(self):
        return self.x*self.x

def main():
    xuan=My_Object()           #My_Object()对象的一个实例

    result1=hasattr(xuan,'x')          #hasattr()用于判断xuan这个对象(类的实例)是否有属性x
    result2=getattr(xuan,'x')   #getattr()属性用于获取xuan这个对象的x属性的值
    print((result1,result2))

    result3=hasattr(xuan,'y')          #用于判断xuan这个对象是否有属性y,很明显没有 类My_Object的__init__只定义了x属性
    #getattr(xuan,'y')          #当一个对象没有属性y时 就会报错,AttributeError 
    result4=getattr(xuan,'y',404)      #当对象xuan没有属性y时就会输出默认值404
    print((result3,result4))

    setattr(xuan,'z',10)       #给对象xuan 设置新的属性z并赋值10 这时xuan这个对象有了x 两个属性
    result5=hasattr(xuan,'z')          #返回True
    result6=getattr(xuan,'z')
    print((result5,result6))

main()

实例属性和类属性

贴一段代码

#实例属性和类属性

class Student(object):
    name='student'  #在类Student内直接定义的name 就是类属性

def main():
    s=Student()  #s 是类Student的一个实例 也拥有类Student的属性name
    result=s.name
    print("\n实例s的name属性的值为:"+result+'\n')

    result2=Student.name   #类也拥有属性name 可以使用类获取类内定义的name属性的值
    print("类Student的name属性的值为:"+result2+'\n')

    s.name='xuanxuan'    #现在修改实例的属性name的值
    result3=s.name
    print("修改实例的name属性值为:"+result3+'\n')

    result4=Student.name  #观察修改实例属性后对类属性有没有影响
    print("类的属性为:"+result4+'\n')

    del s.name      #现在把修改实例s的name属性删掉
    result5=s.name  #观察此时实例的属性name的值 应该是类Student()的属性
    print("删掉实例s的name属性后 再调用实例s的属性 应该就是类Student的name属性值:"+result5+'\n')

    result6=Student.name    #删掉实例的属性 观察对类Student的属性是否有影响
    print("删掉实例s的name属性对类Student的name属性的影响:"+result6+'\n')

main()

“为了统计学生人数,可以给Student类增加一个类属性,每创建一个实例,该属性自动增加:”

这里需要注意count是定义在类Student中的属于类属性当然使用时需要类.属性,而在类的方法中定义时 使用的是self 是针对实例属性,这里是每当生成一个实例,就是调用一次类Student 就得使count增加 所以应该是Student.count+=1 而不是self.count+=1

class Student(object):
    count=0   #类属性
    def __init__(self,name):
        self.name=name
        Student.count+=1

def main():
    xuan=Student('Zhangxuan')
    number=Student.count  #实例可以直接调用类属性,只不过这个类属性是可以变化的,随着每次调用类生成实例而改变
    print("生成第一个实例后count的值为:{}".format(number))
    haha=Student('xixi')
    number=Student.count
    print("生成第二个实例后count的值为:{}".format(number))

main()

使用slots

贴一段代码

 class Student(object):    #定义一个类
...     pass
...
>>> xuan=Student()    #xuan是类Student的一个实例
>>> xuan.name='Zhangxuan'  #可以为实例xuan增加一个属性
>>> xuan.name
'Zhangxuan'
>>>
>>>#下面将为单独一个实例增加某一个方法:
>>>
>>> def set_age(self,age):    #首先定义一个方法,有属性age
...     self.age=age
...
>>> from types import MethodType    
>>> xuan.set_age=MethodType(set_age,xuan)   #这样就可以为Student的实例xuan增加
>>>#一个set_age()方法啦,但是后面创建一个Student的实例时并不具有该set_age()方法
>>> xuan.set_age(22)
>>> xuan.age
22
>>>
>>> hehe=Student()     #为Student创建一个实例hehe
>>> hehe.set_age(23)   #对该实例使用set_age()方法并不可以哦
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'set_age'
>>>
>>>#上面只对类的一个实例增加某方法,现在在类Student 内定义方法,所有实例都可以使用的
>>>
>>> Student.set_age=set_age  #这样使得Student的所有实例都具有该set_age()方法
>>> hehe.set_age(23)
>>> hehe.age
23
>>> haha=Student()
>>> haha.set_age(24)
>>> haha.age
24
>>>
>>>#下面介绍__slotS__ 可以限制类的实例所使用的属性
>>> class Animal(object):
...     __slots__=("name",'age')  #Animal的所有实例只能使用name age两个属性
...
>>> dog=Animal()
>>> dog.name='Husky'
>>> dog.name
'Husky'
>>> dog.age=2
>>> dog.age
2
>>> dog.female='male'     #对于类内__slots__外的其他属性 类的实例均不可以使用
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Animal' object has no attribute 'female'
>>>
>>>#对于类Animal的子类 如果不定义__slots__则不受父类
>>>#__slots__中属性的限制,一旦子类中__slots__ 则子类的实例可以使用的属性除了自身
>>>#__slots__ 也可以使用父类的__slots__中的属性

>>> class animla(Animal):   
...     __slots__=("gender")
...
>>> cat=animla()
>>> cat.name='mimi'
>>> cat.age=1
>>> cat.gender='female'
>>>

使用@property

我真的好崩溃啊 刚才写了那么多 没保存,
简单写一下吧再

“把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作:”

>>>
>>> class Student(object):
...     @property  
...     def get_score(self):
...         return self.score
...     @get_score.setter
...     def set_score(self,score):
...         if not isinstance(value,int):
...             raise ValueError("the type you input is not a int!")
...         if value<0 or value>100:
...             raise ValueError("the value is not in (1,100)")
...         self.score=value
...
>>> xuan=Student()
>>> xuan.score=100
>>> xuan.score
100

已经崩溃到不想注释,,,

>>>
>>> class Student(object):
...     @property
...     def get_birth(self):
...         return self.birth
...     @get_birth.setter
...     def set_birth(self,value):
...         self.birth=value
...     @property
...     def get_age(self):
...         self.age=2018-self.birth
...         return self.age
...
>>> xuan=Student()
>>> xuan.birth=1996
>>> xuan.age
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'age'
>>> xuan.birth
1996
>>> xuan.get_birth=12
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>> xuan.get_age
22
>>>
>>>
>>> class Student(object):
...     @property
...     def get_birth(self):
...         return self.birth
...     @get_birth.setter
...     def set_birth(self,year):
...         self.birth=year
...     @property
...     def get_age(self):
...         self.age=2018-self.birth
...         return self.age
...
>>> xuan=Student()
>>> xuan.birth=1996
>>> xuan.get_birth
1996
>>> xuan.age
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'age'
>>> xuan.get_age
22
>>> xuan.set_birth=1997
>>> xuan.get_age
21

********************************分割线**********************************

以上三个代码其实我写的有点不太对,下面更正一下:( 我真的不想重复刚才写的,,写了那么多,好想骂人,,,,)

下面写的才是对的哦!!!

>>>
>>> class Student(object):
...     @property
...     def birth(self):   #首先设置一个birth属性 
...         return self._birth  #这里self._birth只是为了区分上面的属性birth才加的下划线,表示返回属性birth的值
...     @birth.setter   #注意这里的birth 是属性!!!名字和上面的函数名一样 都是属性,吧方法(函数)变成属性了而已
...     def birth(self,value):  #这里是在设置birth的值
...         self._birth=value
...     @property
...     def age(self):    #对于age属性只设置了可读属性,因为后面并没有setter
...         return (2018-self._birth)
...
>>> xuan=Student()
>>> xuan.birth=1996
>>> xuan.age
22
>>> class Student(object):
...     @property
...     def score(self):
...         return self._score
...     @score.setter
...     def score(self,value):
...         if not isinstance(value,int):
...             raise ValueError("Error")
...         if value<0 or value>100:
...             raise ValueError("Wrong")
...         self._score=value
...
>>> xuan=Student()
>>> xuan.score=100
>>> xuan.score
100

最后写一个作业题:“请利用@property给一个Screen对象加上width和height属性,以及一个只读属性resolution:”

>>> class Screen(object):
...     @property
...     def width(self):
...         return self._width
...     @width.setter
...     def width(self,value1):
...         self._width=value1
...     @property
...     def height(self):
...         return self._height
...     @height.setter
...     def height(self,value2):
...         self._height=value2
...     @property
...     def resolution(self):
...         return self._width*self._height
...
>>> screen=Screen()
>>> screen.width=30
>>> screen.height=40
>>> screem.resolution
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'screem' is not defined
>>> screen.resolution
1200
>>>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值