Python的对象

概念

Python 一切皆对象 object,最典型的对象类 class 与类的实例 instance

一、对象的属性

  • 类中可定义属性。为类创建实例对象时,首先,运行类的 __new__ 方法将类实例化,接着,运行类的 __init__ 初始化方法,其中可定义实例的属性

  • 实例自动继承类的属性,同时也会通过 __init__ 初始化方法获得实例属性,发生命名空间冲突即出现属性名重合时,优先级更高的实例属性会重写 override(如果是函数需要使参数列表与原函数一致,返回类型与原函数一致)继承的类属性

一、对象的方法

Python 中方法 method 的内涵基于面向对象的编程语境,即被对象绑定的函数就是方法,否则就是函数 function

  • 「类方法」需要通过装饰器 @classmethod 包装,需要定义参数 cls,参数传入时 cls 只能是类对象。类方法可以被类与实例对象调用,类对象调用时,Python 会将调用类方法的类对象传入 cls,实例对象调用时,Python 也会将调用类方法的实例对象所继承的类对象传入 cls。在类方法内通过 cls.method() 理论上可以调用除实例方法外的任何方法

  • 「实例方法」需要定义参数 self,参数传入时 self 只能是实例对象,Python 在调用时会将调用实例方法的对象传入 self,因此只能通过实例对象调用实例方法。在实例方法内通过 self.method() 理论上可以调用类中的任何方法

  • 「普通方法」类对象可以直接调用,实例对象只能调用定义 *args 可变参数的普通方法。在普通方法内理论上可以通过 classname.method() 调用除实例方法外的任何方法

  • 「静态方法」通过装饰器 @staticmethod 实现,类与实例对象都能直接调用。在方法内可以通过 classname.method() 调用除实例方法外的任何方法

  • 支持运算符重载 overload(函数名相同但参数不同),可以对类的专有方法 __str__ __add__ 等进行重载从而让类对象及其实例对象能够使用运算符操作

实践

class Toy(object):
    count = 0
    
    def who_toy():
        print(Toy)
        
    @classmethod
    def show_toy_count(cls):
        print('玩具对象的数量 %d' % cls.count, cls)

    @staticmethod
    def hi():
        print('Hello!')

    def __init__(self, name):
        self.name = name
        Toy.count += 1

    def beybey(self):
        self.hi()
        print('Sad!', self)


# 类对象
print(Toy.count)  # 输出:0
Toy.who_toy()  # <class '__main__.Toy'>
Toy.show_toy_count()  # 输出:玩具对象的数量 0 <class '__main__.Toy'>
Toy.hi()  # 输出:Hello!
Toy.beybey()  # 错误语法,self必须指向实例对象,此处实例方法指向类对象而不是实例对象

# 实例对象
toy1 = Toy('泰迪熊')
toy1.hand = 2
print(toy1.name)  # 输出:泰迪熊
print(toy1.hand)  # 输出:2
# 实例对象调用类方法时,与类对象调用类方法无异,但实际上调用仍通过实例对象继承的类对象实现
toy1.show_toy_count()  # 输出:玩具对象的数量 1 <class '__main__.Toy'>
# 实例对象调用静态方法时,与类对象调用静态方法无异,但实际上调用仍通过实例对象继承的类对象
toy1.hi()  # 输出:Hello!
# 实例对象调用实例方法,Python的解释器内部,当我们调用toy1.beybey()时,实际上Python解释成Toy.beybey(toy1)
toy1.beybey()  # 输出:Hello! -> Sad! <__main__.Toy object at 0x104be6a30>
Toy.beybey(toy1)  # 输出:Hello! -> Sad! <__main__.Toy object at 0x104be6a30>
# 隐式实例化并调用实例方法
Toy('哥斯拉').beybey()  # 输出:Hello! -> Sad! <__main__.Toy object at 0x104be69d0> 
print(Toy.hand)  # AttributeError: type object 'Toy' has no attribute 'hand'

# 类与其实例的类型和内存地址
print(type(Toy), id(Toy), type(toy1), id(toy1))  # 输出:<class 'type'> 5274699520 <class '__main__.Toy'> 4374555184
print(int('0x104be6a30', 16))  # 输出:4374555184 


class Cat:  # 或者class Cat()不写父对象形式定义类对象,会默认继承祖先object对象
    name = '小敏'
    # 实例无法使用因为无法匹配参数
    def smile():
        print('哈哈~')
      
    def sad():
        print('呜呜~')
        Cat.run()
        Cat.set()

    @classmethod
    def run(cls):
        print('起飞~')
    
    @classmethod   
    def say(cls):
        print('%s,你好!' % cls.name)
        cls.set()  # 类方法可以调用静态方法
        
    @staticmethod
    def stand():
        print('{},站着!'.format(Cat.name))
        Cat.run()  # 静态方法可以调用类方法
    
    @staticmethod
    def set():
        print('{},坐下!'.format(Cat.name))
                   
    def __init__(self):
    	print(self.name)
        self.name = '胖虎'

    def sleep(self):
        print('呼呼~') 
   

# 类对象
print(Cat.name)  # 小敏
Cat.smile()  # 哈哈~
Cat.sad()  # 呜呜~ -> 起飞~ -> 小敏,坐下
Cat.run()  # 起飞~ 
Cat.say()  # 小敏,你好!-> 小敏,坐下!
Cat.stand()  # 小敏,站着!-> 起飞~
Cat.set()  # 小敏,坐下!
Cat.sleep() TypeError: sleep() missing 1 required positional argument: 'self'

# 实例对象
cat1 = Cat()  # 小敏
print(cat1.name)  # 胖虎
cat1.smile() TypeError: smile() takes 0 positional arguments but 1 was given
cat1.sad() TypeError: sad() takes 0 positional arguments but 1 was given
cat1.run()  # 起飞~
cat1.say()  # 小敏,你好!-> 小敏,坐下!
cat1.stand()  # 小敏,站着!-> 起飞~
cat1.set()  # 小敏,坐下!
cat1.sleep()  # 呼呼~


class Vector:

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)

    def __repr__(self):
        return f'Vector({self.x}, {self.y})'

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y


v1 = Vector(3, 4)
v2 = Vector(5, 6)
print(Vector(3, 4) + Vector(3, 4))  # 输出:Vector(6, 8)
print(v1 == v2)  # 输出:False


- **祖先对象中包含的基本方法**

```python
print(dir(object))

['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

总结

Python 中最核心的对象 object 是类 class ,定义类通常要编写类属性、普通方法、实例初始化方法、实例方法、类方法、静态方法等。把类及其实例比作函数中的主函数和子函数,那么类属性可认为是全局变量,实例属性可认为是局部变量。类的各方法间并不是彼此毫不相干,而是有着很强的共性,设计的目的是为了提升编程效率,具体使用何种方法并无绝对灵活运用即可,大可不必局限在抽象定义之中

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昊大侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值