自学Python 27 属性

Python 面向对象编程技术(四)



  属性是对现实世界中实体特征的抽象,提供了对类或对象性质的访问。举一个例子,长方形是一个对象,则长和宽就是长方形的两个属性。

注意:属性反映了面向对象的编程思想,即不能直接操作类的字段。属性隔离了字段,而且能对要赋值的字段进行监测,合乎要求的才会被允许。属性是这样的成员:它提供了灵活的机制来读取、编写或计算某个私有字段的值。可以像使用公共数据成员一样使用属性,但实际上它们是称作“访问器”的特殊方法。这使得可以轻松访问数据,此外还有助于提高方法的安全性和灵活性。


一、认识属性

  在Python程序中,属性是对类进行建模必不可少的内容,上一篇文章介绍的方法是用来操作数据的,而和操作相关的大部分内容都和下面将要讲解的属性有关。我们既可以在构造方法中定义属性,也可以在类中的其他方法中使用定义的属性。在本篇文章之前的内容中,已经多次用到了属性,例如在上一篇的实例中, “name”和“age”都是属性,具体实现代码如下所示:

class Dog:
    "小狗的类"
    def __init__(self,name,age):
        "初始化属性name和agw"
        self.name = name
        self.age = age
    def wang(self):
        "模拟狗狗汪汪叫"
        print(self.name.title() + "汪汪")
    def shen(self):
        "模拟狗狗伸舌头"
        print(self.name.title() + "伸舌头")
my_dog = Dog("大狗",6)
your_dog = Dog("小狗",3)
print("霍老二爱犬的名字是" + my_dog.name.title() + ".")
print("霍老二的爱犬已经" + str(my_dog.age) + "岁了!")
my_dog.wang()
print("\n你爱犬的名字是" + your_dog.name.title() + ".")
print("你的爱犬已经" + str(your_dog.age) + "岁了!")
your_dog.wang()

  在上述代码中,在构造方法__init__()中创建一个表示特定小狗的实例,并使用我们提供的值来设置属性name和 age。在my_dog.name.title()和str(my_dog.age)中点运算符“.访问了实例属性,运算符表示法在 Python中很常用,这种语法演示了Python如何获取属性的值。在上述代码中,Python先找到实例my_dog,再查找与这个实例相关联的属性name。在类Dog中引用这个属性时,使用的是self.name。同样道理,可以使用同样的方法来获取
  属性age的值。在代码“my dog.name.title()”中,将my_dog的属性name的值改为首字母是大写的,当然我们代码中用的是汉字,读者可以将其设置为字母试一试。在代码行“str(my_dog.age)”中,将my_dog的属性age的值“6”转换为字符串。

二、类属性和实例属性

  在Python程序中,通常将属性分为实例属性和类属性两种,具体说明如下所示。
   (1)实例属性:是同一个类的不同实例,其值是不相关联的,也不会互相影响的,定义时使用“self.属性名”的格式定义,调用时也使用这个格式调用。
  (2)类属性:是同一个类的所有实例所共有的,直接在类体中独立定义,引用时要使用“类名.类变量名”的格式来引用,只要是某个实例对其进行修改,就会影响其他所有这个类的实例。演示实例:

class X_Property:               #定义类X_Property
    class_name = "X_Property"   #设置类的属性
    def __init__(self,x=0):     #构造方法
        self.x = x              #设置实例属性
    def class_info(self):       #定义方法输出信息
        print("类变量值:",X_Property.class_name)
        print('实例变量名',self.x)
    def chng(self,x):           #定义方法修改实例属性
        self.x = x              #引用实例属性
    def chng_cn(self,name):     #定义方法修改类属性
        X_Property.class_name = name
aaa = X_Property()              #定义类X_Property的实例化对象aaa
bbb = X_Property()              #定义类X_Property的实例化对象bbb
print("初始化两个实例")
aaa.class_info()
bbb.class_info()
print("修改实例变量")
print("修改aaa实例变量")
aaa.chng(3)
aaa.class_info()
bbb.class_info()
print("修改bbb实例变量")
bbb.chng(10)
aaa.class_info()
bbb.class_info()
print("修改类变量")
print("修改aaa类变量")
aaa.chng_cn("aaa")
aaa.class_info()
bbb.class_info()
print("修改bbb类变量")
bbb.chng_cn("bbb")
aaa.class_info()
bbb.class_info()

  在上述实例代码中,首先定义了类X_Property, 在类中有一个类属性class_name 和一个实例属性x,两个分别修改实例属性和类属性的方法。然后分别实例化这个类,并调用这两个类实例来修改类属性和实例属性。对于实例属性来说,两个实例相互之间并不联系,可以各自独立地被修改为不同的值。而对于类属性来说,无论哪个实例修改了它,都会导致所有实例的类属性值发生变化。执行后会输出:
在这里插入图片描述

三、设置属性的默认值

  在Python程序中,类中的每个属性都必须有初始值,并且有时可以在方法__init__()中指定某个属性的初始值是0或空字符串。如果设置了某个属性的初始值,就无须在__init__()中提供为属性设置初始值的形参。假设有这么一个场景,年底将至,想换辆新车,初步中意车型是奔驰E级。例如在下面的实例中,定义了一个表示汽车的类,在类中包含了和汽车有关的属性信息:

class Car():
    "奔驰!"
    def __init__(self,manufacturer,model,year):
        "初始化操作,创建描述汽车的属性"
        self.manufacturer = manufacturer
        self.model = model
        self.year = year
        self.odometer_reading = 0
    def get_descriptive_name(self):
        "返回描述信息"
        long_name = str(self.year) + ' ' + self.manufacturer + ' ' + self.model
        return long_name.title()
    def read_odometer(self):
        "行驶里程"
        print("新车的仪表显示行驶里程是" +str (self.odometer_reading) + "公里!")
my_new_car = Car("Benz","E300L",2009)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()

  对上述实例代码的具体说明如下所示。
  (1)首先定义了方法__init__(),这个方法的第一个形参为self, 三个形参: manufacturer、model和year。运行后方法__init__()接受这些形参的值,并将它们存储在根据这个类创建的实例的属性中。创建新的Car实例时,我们需要指定其品牌、型号和生产日期。
  (2)在第8行代码中添加了一个名odometer_reading 的属性,并设置其初始值总是为0。
  (3)在第9行代码定义了一个名为get_descriptive_name(的方法,在里面使用属性year、manufacturer 和model创建了一个对汽车进行描述的字符串,在程序中我们无须分别打印输出每个属性的值。为了在这个方法中访问属性的值,分别使用了self.manufacturer、self.model和self.year格式进行访问。
  (4)在第13行代码中定义了方法readodometer(),功能是获取当前奔驰汽车的行驶里程。
  (5)在倒数第3行代码中,为了使用类Car,根据类Car创建了一个实例,并将其存储到变量my_new_car中。然后调用方法get_descriptive_name(),打印输出我当前想购买的是哪一款汽车。
  (6)在最后1行代码中,打印输出当前奔驰汽车的行驶里程。因为设置的默认值是0,所以会显示行驶里程为0。执行后会输出:
在这里插入图片描述

四、修改属性的值

  在Python程序中,可以使用如下两种不同的方式修改属性的值。
  ●直接通过实例进行修改;
  ●通过自定义方法修改。
  在下面的内容中,将详细讲解.上述两种修改属性值方法的知识。
  1. 直接通过实例进行修改
  在Python程序中,可以直接通过实例的方式修改一个属性的值。例如在下面的实例代码中,将新车奔驰E300L的行驶里程修改为12公里。

my_new_car = Car("Benz","E300L",2009)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 12			#修改里程数
my_new_car.read_odometer()

  在上述代码中,使用点运算“.”来直接访问并设置汽车的属性odometer_reading,并将属性odometer_reading值设置为12,执行结果如下:
在这里插入图片描述
  2.自定义方法修改
  在Python程序中,可以自定义编写一个专有方法来修改某个属性的值。这是可以无须直接访问属性,而只是将值传递给自定义编写的方法,并在这个方法内部进行修改即可。例如在下面的实例代码中,通过自定义方法update_odometer()将行驶里程修改为15公里:

    def update_odometer(self,mileage):
        "修改行驶里程"
        if mileage>= self.odometer_reading:
            self.odometer_reading = mileage
        else:
            ("这是一个不合理的数据")
my_new_car = Car("Benz","E300L",2019)
print(my_new_car.get_descriptive_name())
my_new_car.update_odometer(15)
my_new_car.read_odometer()

  在上述实例代码中定义了一个自定义方法update_odomer(),此方法可以接受一个行驶里程值,并将其存储到self.odometer_reading 中。并且设置在修改属性前检查指定的里程数据是否合理。如果新指定的里程大于或等于原来的里程“self.odometer_reading” ,则将里程数据改为新设置的里程数据。否则就发出提醒,输出“这是一个不合理的数据!”的提示。在倒数第2行代码中,调用自定义方法update_odometer() 将行驶里程修改为15。执行后会输出:
在这里插入图片描述

五、使用私有属性

  在前面一篇文章的内容中已经讲解了私有方法的知识,已经了解到只要在属性名或方法名前加上两个下画线“__”,那么这个属性或方法就会为私有的了。在Python程序中,私有属性不能在类的外部被使用或直接访问。当在类的内部使用私有属性时,需要通过“self. __属性名”的格式使用。例如在下面的实例中演示了在类内使用私有属性过程。实例如下:

class Person:
    def __init__(self):
        self.__name="haha"
        self.age = 22
    def get_name(self):
        return self.__name
    def get_age(self):
        return self.age
person = Person()
print (person.get_name())
print (person.get_age())

  在上述代码中,“__name”是私有属性。如果直接访问私有属性和私有方法,系统会提示找不到相关的属性或者方法。执行后输出:
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值