Python 学习笔记(十一):面向对象编程(类的特殊操作)

本文深入探讨Python类的高级特性,包括属性的访问控制、运算符重载、使用property装饰器、__slots__魔法、静态方法和类方法,以及如何查看类或对象的属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.访问可见性问题

  • 对象属性的访问权限包括私有的、受保护的和公开的,而对象的方法通常是公开的。如果希望属性是私有的,即不允许外界访问,在给属性命名时可以用两个下划线作为开头,如:
class Car(object):

    def __init__(self, model="BMW", year=2019, foo='abc'):
        self.model = model
        self.year = year
        self.__foo = foo

>>> car = Car()
>>> car.model
BMW
>>> car.__foo   #无法从外界获取私有属性
AttributeError: 'Car' object has no attribute '__foo'
        

2.类可以截获Python运算符

用类写成的对象可以截获并响应应用在内置类型上的运算:加法、切片、打印和点号运算等,这也称为运算符重载,以下是运算符重载的概要:

  • 以双下划线命名的方法__X__构造,python语言替每种运算和特殊命名的方法之间定义了固定不变的映射关系, __init__是最常用的运算符重载方法
  • 当实例出现内置运算时,这类方法会自动调用。如实例对象继承了__add__方法,当对象出现在 + 表达式内时,该方法就会调用
  • 类可覆盖多数内置类型运算
  • 运算符覆盖方法没有默认值,而且也不需要。如果类没有定义或继承运算符重载方法,则相应的运算在类实例中并不支持,如果没有__add__,+表达式就会引发异常
class Firstclass(object):
    
    def __init__(self, data):
        self.data = data
        
    def __add__(self, other):
        return Firstclass(self.data + other + '!')
    
    def __str__(self):
        return 'Firstclass: %s' % self.data
                
a = Firstclass('abc')
print(a)
b = a + 'xyz'
print(b)
>>> Firstclass: abc
>>> Firstclass: abcxyz!

3.property 装饰器

一般我们不建议把属性设置为私有的,但如果直接将属性暴露给外界也会有问题,如没有办法检查赋给属性的值是否有效,因此建议将属性以单下划线开头,来暗示属性是受保护的,不建议外界直接访问,那么如果想访问属性可以通过属性的 getter(访问器)和setter(修改器)方法进行对应的操作。如果要做到这点,就可以考虑使用@property包装器来包装getter和setter方法,使得对属性的访问既安全又方便,如:

class Person(object):
    
    def __init__(self, name, age):
        self._name = name
        self._age = age
    
    # 访问器 -getter方法
    @property
    def name(self):
        return self._name
    
    # 访问器 -getter方法
    @property
    def age(self):
        return self._age
    
    # 修改器 - setter方法
    @age.setter
    def age(self, age):
        self._age = age
        
    def play(self):
        if self._age <= 18:
            print('%s正在喝可乐.' % self._name)
        else:
            print('%s正在喝酒.' % self._name)
person = Person('Randoll', 22)
person.play()
print(person.age)
person.age = 16
person.play()
print(person.age)

>>> Randoll正在喝酒.
>>> 22
>>> Randoll正在喝可乐.
>>> 16

3.__slots__魔法

通过定义__slots__变量可以限定自定义类型的对象只能绑定某些属性,但只对当前类生效,对子类无效

class Person(object):

    # 限定Person对象只能绑定_name, _age, _number属性
    __slots__ = ('_name', '_age', '_number')

    def __init__(self, name, age):
        self._name = name
        self._age = age

    @property
    def name(self):
        return self._name

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, age):
        self._age = age

    def play(self):
        if self._age <= 18:
            print('%s正在喝可乐.' % self._name)
        else:
            print('%s正在喝酒.' % self._name)

person = Person('王大锤', 22)
person.play()
person._number = 123456
person._gender = 'male'

>>> AttributeError: 'Person' object has no attribute '_gender'

4.静态方法和类方法

之前在类中定义的都是对象方法,都是发送给对象的消息;但类中的方法除了对象方法,也可以是静态方法,如:

from math import sqrt

#定义一个"三角形"类
class Triangle(object):

    def __init__(self, a, b, c):
        self._a = a
        self._b = b
        self._c = c
    #验证是否能构成三角形
    @staticmethod
    def is_valid(a, b, c):
        return a + b > c and b + c > a and a + c > b
    #计算三角形周长的方法
    def perimeter(self):
        return self._a + self._b + self._c

a, b, c = 3, 4, 7
# 静态方法和类方法都是通过给类发消息来调用的
if Triangle.is_valid(a, b, c): #在构成对象前调用类的静态方法
    t = Triangle(a, b, c)
    print(t.perimeter())
else:
    print('无法构成三角形.')

>>> 无法构成三角形.

和静态方法比较类似,Python还可以在类中定义类方法,类方法的第一个参数约定名为cls,它代表的是当前类相关的信息的对象(类本身也是一个对象,有的地方也称之为类的元数据对象),通过这个参数我们可以获取和类相关的信息并且可以创建出类的对象,如:

from time import time, localtime, sleep

class Clock(object):
    
    """数字时钟"""

    def __init__(self, hour=0, minute=0, second=0):
        self._hour = hour
        self._minute = minute
        self._second = second
        
    @classmethod
    def now(cls):
        ctime = localtime(time())
        return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)
    
    def show(self):
        """显示时间"""
        return '%02d:%02d:%02d' % \
               (self._hour, self._minute, self._second)

# 通过类方法创建对象并获取系统时间
clock = Clock.now()
clock.show()

>>> '15:11:47'

5.查看类或者对象的属性

>>> Firstclass.__bases__  #查看当前类的超类
(object,)

>>> Firstclass.__dict__.keys() #查看当前类的属性
dict_keys(['__module__', '__init__', '__add__', '__str__', 'mul', '__dict__', '__weakref__', '__doc__'])

>>> a.__dict__.keys()    #查看对象的属性
dict_keys(['data'])

>>> a.__class__  #查看实例关联的类
__main__.Firstclass
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值