第四章 面向对象编程 -- 自定义类、属性、方法和函数

第零章 学前准备
第一章 数据结构 – 基本数据类型
第一章 数据结构 – 字符串
第一章 数据结构 – 列表、元组和切片
第一章 数据结构 – 字典
第一章 数据结构 – 集合
第一章 – 数组、队列、枚举
第一章 数据结构 – 序列分类
第二章 控制流程
第三章 函数也是对象 – 函数定义以及参数
第三章 函数也是对象 – 高阶函数以及装饰器
第三章 函数也是对象 – lambda 表达式、可调用函数及内置函数
第四章 面向对象编程 – 自定义类、属性、方法和函数


第四章 面向对象编程 – 自定义类、属性、方法和函数

面向对象编程

4.1 自定义类语法

  1. 如下定义步骤,类定义的关键字是class,一般类的名称方式使用大驼峰法命名方式命名,如下:FrenchDeck,类名后面有小括号,指定父类,python内基类是object,默认所有类均继承object。如果父类仅有object类,可以省略继承的写法,比如:class FrenchDeck:class FrenchDeck():
  2. 每一个类中的方法第一个参数都是selfself就是类对应的实例对象。
Card = collections.namedtuple('Card', ['rank', 'suit'])


class FrenchDeck(object):
    ranks = [str(n) for n in range(2, 11)]+list('JQKA')
    suits = 'spades diamonds clubs hearts'.split()

    def __init__(self):
        self._cards = [Card(rank, suit)
                       for suit in self.suits for rank in self.ranks]

    def __len__(self):
        return len(self._cards)

    def __getitem__(self, position):
        return self._cards[position]

4.2 属性

4.2.1 类属性

类属性其实就是定义在类中的变量。因为是定义在类中,所以,该类的所有实例共享类属性

类属性的访问可以使用类名也可以使用实例访问。

4.2.2 实例属性

实例属性是类实例的变量马。因为是定义在类中,该类的所有实例单独管理自己的实例属性。

实例属性的访问只能使用实例访问,不能使用类名访问。

4.2.3 特殊属性

  1. object.__dict__:一个字典或其他类型的映射对象,用于存储对象的(可写)属性。
  2. instance.__class__:类实例所属的类。
  3. class.__bases__:由类对象的基类所组成的元组。
  4. class.__base__:类的基类。
  5. definition.__name__:类、函数、方法、描述器或生成器实例的名称。
  6. definition.__qualname__:类、函数、方法、描述器或生成器实例的 qualified name。3.3 新版功能.
  7. class.__mro__:此属性是由类组成的元组,在方法解析期间会基于它来查找基类。
  8. class.__subclasses__():每个类都存有对直接子类的弱引用列表。本方法返回所有存活引用的列表。列表的顺序按照子类定义的排列。

4.2.4 私有属性和"受保护的"属性

Python 不能像 Java 那样使用 private 修饰符创建私有属性,但是 Python 有个简单的机制,能避免子类意外覆盖“私有”属性。举个例子。有人编写了一个名为 Dog 的类,这个类的内部用到了 mood 实例属性,但是没有将其开放。现在,你创建了 Dog 类的子类: Beagle 。如果你在毫不知情的情况下又创建了名为 mood 的实例属性,那么在继承的方法中就会把 Dog 类的 mood 属性覆盖掉。这是个难以调试的问题。为了避免这种情况,如果以 __mood 的形式(两个前导下划线,尾部没有或最多有一个下划线)命名实例属性, Python 会把属性名存入实例的 __dict__ 属性中,而且会在前面加上一个下划线和类名。因此,对 Dog 类来说, __mood 会变成 _Dog__mood ;对 Beagle 类来说,会变成 _Beagle__mood 。这个语言特性叫名称改写( name mangling )。

Python 解释器不会对使用单个下划线的属性名做特殊处理,不过这是很多 Python 程序员严格遵守的约定,他们不会在类外部访问这种属性。遵守使用一个下划线标记对象的私有属性很容易,就像遵守使用全大写字母编写常量那样容易。Python文档的某些角落把使用一个下划线前缀标记的属性称为“受保护的”属性。使用 self._x 这种形式保护属性的做法很常见,但是很少有人把这种属性叫作“受保护的”属性。有些人甚至将其称为“私有”属性。

import doctest


class Person:
    """
    >>> p = Person("xiaohong", "♀",18)
    >>> p._Person__age
    18
    >>> p.__age
    Traceback (most recent call last):
    ...
    AttributeError: 'Person' object has no attribute '__age'
    """

    def __init__(self, name, gender, age):
        self.name = name
        self.gender = gender
        self.__age = age


doctest.testmod()
TestResults(failed=0, attempted=11)

4.3 方法和函数

4.3.1 实例方法

实例方法是操作实例的方法,传递的第一个参数是类的实例,参数名约定为 self不强制为self )。

4.3.2 类方法

定义操作类,而不是操作实例的方法。定义类方法需要使用装饰器 classmethodclassmethod 改变了调用方法的方式,因此类方法的第一个参数是类本身,而不是实例。 classmethod 最常见的用途是定义备选构造方法,因为操作的是类,可以通过类新建类的实例。按照约定,类方法的第一个参数名为 cls (但是 Python 不介意具体怎么命名)。

4.3.2 静态方法

定义静态方法需要使用装饰器 staticmethodstaticmethod 装饰器也会改变方法的调用方式,但是第一个参数不是特殊的值。其实,静态方法就是普通的函数,只是碰巧在类的定义体中,而不是在模块层定义。

class Person:
    quantity = 202178.37e9

    def __init__(self, name, gender, age):
        self.name = name
        self.gender = gender
        self.age = age

    @classmethod
    def from_id_card(cls, name, gender, age, id_card):
        print(cls)
        instance = cls(name, gender, age)
        instance.id_card = id_card
        return instance

    @staticmethod
    def number_add(n1, n2):
        return n1+n2

    def walk(self, speed):
        print(self, f"move 速度{speed}迈")

    def run(people, speed):
        print(people, f"move 速度{speed}迈")


p1 = Person("xiaojuan", "♀", "18")
p2 = Person("xiaoyang", "♂", "17")
print('p1.quantity', p1.quantity, "Person.quantity", Person.quantity)
print(p1.name, p1.gender)
print(p2.name, p2.gender)
Person.quantity = p1.quantity//2
print(p2.quantity)
# 如果使用p1.quantity修改Person.quantity值呢?
p1.quantity = p1.quantity//2*2
print(p2.quantity)
print("*"*30)
p1.walk(80)
p1.run(180)
print("*"*30)
p3 = Person.from_id_card("xiaoshuai", "♂", "10", "10000000")
print(p3.id_card)
print(Person.number_add(1, 2))
p1.quantity 202178370000000.0 Person.quantity 202178370000000.0
xiaojuan ♀
xiaoyang ♂
101089185000000.0
101089185000000.0
******************************
<__main__.Person object at 0x00000162F3A77EB0> move 速度80迈
<__main__.Person object at 0x00000162F3A77EB0> move 速度180迈
******************************
<class '__main__.Person'>
10000000
3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值