Python:静态方法和类方法

之前,在类中定义的方法都是给对象的方法
实际上我们写在类中的方法不都是对象的方法
例如:
我们定义一个三角形类,通过传入三边的边长来构造三角形,并提供计算周长和面积的方法
但是传入三条边的长度不一定都能构造出三角形,
我们可以先写一个方法来验证三条边能否构成三角形
这个方法肯定不是对象方法,因为这件事情是我在创建三角形对象之前做的
这个方法属于三角形类而不属于三角形对象

单词部分

triangle    英[ˈtraɪæŋɡl]
美[ˈtraɪæŋɡl]
n. 三角形; 三角形物体; 三角铁(打击乐器); 三角关系;
[例句]This design is in pastel colours with three rectangles and three triangles
这一设计由淡色的3个长方形和3个三角形构成。
[其他]   复数:triangles


static 英[ˈstætɪk]
美[ˈstætɪk]
adj.   静止的; 静态的; 停滞的; 静力的;
n. 天电(干扰); 静电; 静力学;
[例句]The number of young people obtaining qualifications has remained static or decreased
获得资格证的年轻人数量一直维持不变或出现下降。
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 a + c > b and b + c > a

    # 对象方法
    def perimeter(self):
        return self._a + self._b + self._c

    # 海伦公式 面积 = 半周长*(半周长-a)*(半周长-b)*(半周长-c)开平方
    def area(self):
        half = self.perimeter() / 2
        return sqrt(half * (half - self._a) * (half - self._b) * (half - self._c))


def main():
    a, b, c = 3, 4, 5
    if Triangle.is_valid(a, b, c):
        # 创建对象
        t = Triangle(a, b, c)
        print(t.perimeter())
        # 也可以给类发消息来调用对象方法但是要传入接受消息的对象作为参数
        print(Triangle.area(t))
    else:
        print('无法构成三角形')


if __name__ == '__main__':
    main()

示例图:

这里使用到了海伦公式,海伦公司需要勾股定理,我们来证明一下:

勾股定理:

图示

化解得到:

海伦公式:

勾股定理和海伦公司大家自己证明一下吧,感觉开个新专栏讲数学也不错~~~哈哈哈,吾乃天才

# 类方法

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


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):
        current_time = time.localtime(time.time())
        return cls(current_time.tm_hour, current_time.tm_min, current_time.tm_sec)

    def run(self):
        """走字"""
        self._second += 1
        if self._second == 60:
            self._second = 0
            self._minute += 1
            if self._minute == 60:
                self._minute = 0
                self._hour = 0
                if self._hour == 24:
                    self._hour = 0

    def show(self):
        """显示时间"""
        # 占位符 留两个位置
        return '%2d:%2d:%2d' % (self._hour, self._minute, self._second)


def main():
    # 通过类方法创建对象并获取系统时间
    clock = Clock.now()
    while True:
        print(clock.show())
        time.sleep(1)
        clock.run()


if __name__ == '__main__':
    main()

示例图:

"""
类之间的关系
is - a : 继承(泛化) 比如说学生和人的关系,手机和电子产品的关系都属于继承关系
has - a : 关联关系  部门和员工的关系,汽车和引擎的关系都属于关联关系
          关联如果是整体和部分的关联,称为聚合关系
          如何整体进一步负责了部分的生命周期(整体和部分不可分割,同时同在也同时消亡),这种关系是合成关系
use - a : 依赖    比如司机有一个驾驶的方法,其中参数用到了汽车,司机和汽车就是依赖关系
"""

在已有类的基础上完成某些操作,也可以在已有类的基础上创建新的类,这些都是实现代码复用的重要手段,复用现有的代码不仅可以减少开发的工作量,也利于代码的维护和管理。

大学的UML课本不错

UML面向对象设计基础

提取码: jy9x

资源链接放在这里啦

"""
类之间的关系
is - a : 继承(泛化) 比如说学生和人的关系,手机和电子产品的关系都属于继承关系
has - a : 关联关系  部门和员工的关系,汽车和引擎的关系都属于关联关系
          关联如果是整体和部分的关联,称为聚合关系
          如何整体进一步负责了部分的生命周期(整体和部分不可分割,同时同在也同时消亡),这种关系是合成关系
use - a : 依赖    比如司机有一个驾驶的方法,其中参数用到了汽车,司机和汽车就是依赖关系
"""
"""
在已有类的基础上完成某些操作,
也可以在已有类的基础上创建新的类,
这些都是实现代码复用的重要手段,
复用现有的代码不仅可以减少开发的工作量,
也利于代码的维护和管理。
"""
'''
在已有类的基础上创建新类,
这其中的一种做法就是让一个类从另外一个类那里把属性和方法全部继承下来
从而减少重复代码的编写。
提供继承信息的我们称为父类,也叫超类或者基类
得到继承信息的我们称为子类,也叫派生类或者衍生类
子类除了可以继承父类提供的属性和方法,还可以定义自己的属性和方法
子类比父类拥有更多的能力
在实际开发中,我们通常会用子类对象替换一个父类对象,这是面向对象编程中常见行为
对应的原则称为里氏替换原则
'''
# 继承和多态

class Person(object):
    """人"""

    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):
        print('%s正在快乐的玩耍' % self._name)

    def watch_av(self):
        if self._age >= 18:
            print('%s正在观看爱情动作片' % self._name)
        else:
            print('%s正在画圈圈' % self._name)


class Student(Person):
    """学生"""

    def __init__(self, name, age, grade):
        super().__init__(name, age)
        self._grade = grade

    @property
    def grade(self):
        return self._grade

    @grade.setter
    def grade(self, grade):
        self._grade = grade

    def study(self, course):
        print('%s的%s正在学习%s' % (self._grade, self._name, course))


class Teacher(Person):
    def __init__(self, name, age, title):
        super().__init__(name, age)
        self._title = title

    @property
    def title(self):
        return self._title

    @title.setter
    def title(self, title):
        self._title = title

    def teach(self, course):
        print('%s%s正在讲%s' % (self._name, self._title, course))


def main():
    stu = Student('王大锤', 15, '初三')
    # 使用子类的方法
    stu.study('数学')
    # 使用父类的方法
    stu.watch_av()
    t = Teacher('她与断剑', 22, '叫狮')
    # 使用子类的方法
    t.teach('python')
    # 使用父类的方法
    t.watch_av()


if __name__ == '__main__':
    main()

示例图:

'''

override   英[ˌəʊvəˈraɪd]
美[ˌoʊvərˈraɪd]
v. (以权力) 否决,推翻,不理会; 比…更重要; 凌驾; 超驰控制,超控(使自动控制暂时失效,改用手工控制);
[例句]The welfare of a child should always override the wishes of its parents
孩子的幸福安康应该永远比父母的愿望来得更重要。
[其他]   第三人称单数:overrides 现在分词:overriding 过去式:overrode 过去分词:overridden

poly   英[ˈpɒli]
美[ˈpɑːli]
n. 同 polytechnic; (旧时英国的)理工学院(现在多已改为大学) ;
[例句]He portrays the psyche as poly-centric.
在他的描绘中精神是多中心的。
[其他]   复数:polys

morphology
英[mɔːˈfɒlədʒi]
美[mɔːrˈfɑːlədʒi]
n. 形态学; 形态论; 词法;
[例句]This paper the morphology of gastric glands and mucous surface in the hatchlings of alligator sinensis.
本文观察了初孵扬子鳄胃粘膜表面及胃腺的形态。

子类继承了父类的方法之后,可以对父类已有的方法给出一个新的版本,即为重写(override)
通过方法重写可以让父类的同一个行为在子类中拥有不同的版本
当我们调用这个经过子类改写的方法时,不同的子类对象会表现出不同的行为,即为多态(poly-morphology)
'''

多态

"""
下面代码中,我们将Pet处理为一个抽象类,就是不能够创建对象的类,
这种类就是专为其它类去继承它
Python从语法层并没有提供像java/c#那样的抽象类支持
通过abc模块的ABCMeta元类和abstactmethod包装器来达到抽象类的效果

重点:
下面代码中
Dog和Cat两个子类分别对Pet类中的make_voice抽象方法进行了重写
调用方法时,同样的方法做了不同的事情(多态行为)
"""
from abc import ABCMeta, abstractmethod


class Pet(object, metaclass=ABCMeta):
    """宠物"""

    def __init__(self, nickname):
        self._nickname = nickname

    @abstractmethod
    def make_voice(self):
        """发出声音"""
        pass


class Dog(Pet):
    """狗"""

    def make_voice(self):
        print('%s:汪汪汪...' % self._nickname)


class Cat(Pet):
    """猫"""

    def make_voice(self):
        print('%s:喵喵喵...' % self._nickname)


def main():
    pets = [Dog('旺财'), Cat('凯蒂'), Dog('大黄')]
    for pet in pets:
        pet.make_voice()


if __name__ == '__main__':
    main()

示例图:

发布了52 篇原创文章 · 获赞 34 · 访问量 2608

猜你喜欢

转载自blog.csdn.net/weixin_38114487/article/details/103966367
今日推荐