重庆分公司,新征程启航

为企业提供网站建设、域名注册、服务器等服务

python实验抽象函数的简单介绍

如何在Python中使用static,class,abstract方法

方法在Python中是如何工作的

创新互联是一家集网站建设,桐梓企业网站建设,桐梓品牌网站建设,网站定制,桐梓网站建设报价,网络营销,网络优化,桐梓网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。

方法就是一个函数,它作为一个类属性而存在,你可以用如下方式来声明、访问一个函数:

Python

class Pizza(object):

... def __init__(self, size):

... self.size = size

... def get_size(self):

... return self.size

...

Pizza.get_size

unbound method Pizza.get_size

Python在告诉你,属性_get_size是类Pizza的一个未绑定方法。这是什么意思呢?很快我们就会知道答案:

Python

Pizza.get_size()

Traceback (most recent call last):

File "stdin", line 1, in module

TypeError: unbound method get_size() must be called with Pizza instance as first argument (got nothing instead)

我们不能这么调用,因为它还没有绑定到Pizza类的任何实例上,它需要一个实例作为第一个参数传递进去(Python2必须是该类的实例,Python3中可以是任何东西),尝试一下:

Python

Pizza.get_size(Pizza(42))

42

Pizza.get_size(Pizza(42))

42

太棒了,现在用一个实例作为它的的第一个参数来调用,整个世界都清静了,如果我说这种调用方式还不是最方便的,你也会这么认为的;没错,现在每次调用这个方法的时候我们都不得不引用这个类,如果不知道哪个类是我们的对象,长期看来这种方式是行不通的。

那么Python为我们做了什么呢,它绑定了所有来自类_Pizza的方法以及该类的任何一个实例的方法。也就意味着现在属性get_size是Pizza的一个实例对象的绑定方法,这个方法的第一个参数就是该实例本身。

Python

Pizza(42).get_size

bound method Pizza.get_size of __main__.Pizza object at 0x7f3138827910

Pizza(42).get_size()

42

和我们预期的一样,现在不再需要提供任何参数给_get_size,因为它已经是绑定的,它的self参数会自动地设置给Pizza实例,下面代码是最好的证明:

Python

m = Pizza(42).get_size

m()

42

更有甚者,你都没必要使用持有Pizza对象的引用了,因为该方法已经绑定到了这个对象,所以这个方法对它自己来说是已经足够了。

也许,如果你想知道这个绑定的方法是绑定在哪个对象上,下面这种手段就能得知:

Python

m = Pizza(42).get_size

m.__self__

__main__.Pizza object at 0x7f3138827910

# You could guess, look at this:

...

m == m.__self__.get_size

True

显然,该对象仍然有一个引用存在,只要你愿意你还是可以把它找回来。

在Python3中,依附在类上的函数不再当作是未绑定的方法,而是把它当作一个简单地函数,如果有必要它会绑定到一个对象身上去,原则依然和Python2保持一致,但是模块更简洁:

Python

class Pizza(object):

... def __init__(self, size):

... self.size = size

... def get_size(self):

... return self.size

...

Pizza.get_size

function Pizza.get_size at 0x7f307f984dd0

静态方法

静态方法是一类特殊的方法,有时你可能需要写一个属于这个类的方法,但是这些代码完全不会使用到实例对象本身,例如:

Python

class Pizza(object):

@staticmethod

def mix_ingredients(x, y):

return x + y

def cook(self):

return self.mix_ingredients(self.cheese, self.vegetables)

这个例子中,如果把_mix_ingredients作为非静态方法同样可以运行,但是它要提供self参数,而这个参数在方法中根本不会被使用到。这里的@staticmethod装饰器可以给我们带来一些好处:

Python不再需要为Pizza对象实例初始化一个绑定方法,绑定方法同样是对象,但是创建他们需要成本,而静态方法就可以避免这些。

Python

Pizza().cook is Pizza().cook

False

Pizza().mix_ingredients is Pizza.mix_ingredients

True

Pizza().mix_ingredients is Pizza().mix_ingredients

True

可读性更好的代码,看到@staticmethod我们就知道这个方法并不需要依赖对象本身的状态。

可以在子类中被覆盖,如果是把mix_ingredients作为模块的顶层函数,那么继承自Pizza的子类就没法改变pizza的mix_ingredients了如果不覆盖cook的话。

类方法

话虽如此,什么是类方法呢?类方法不是绑定到对象上,而是绑定在类上的方法。

Python

class Pizza(object):

... radius = 42

... @classmethod

... def get_radius(cls):

... return cls.radius

...

Pizza.get_radius

bound method type.get_radius of class '__main__.Pizza'

Pizza().get_radius

bound method type.get_radius of class '__main__.Pizza'

Pizza.get_radius is Pizza().get_radius

True

Pizza.get_radius()

42

无论你用哪种方式访问这个方法,它总是绑定到了这个类身上,它的第一个参数是这个类本身(记住:类也是对象)。

什么时候使用这种方法呢?类方法通常在以下两种场景是非常有用的:

工厂方法:它用于创建类的实例,例如一些预处理。如果使用@staticmethod代替,那我们不得不硬编码Pizza类名在函数中,这使得任何继承Pizza的类都不能使用我们这个工厂方法给它自己用。

Python

class Pizza(object):

def __init__(self, ingredients):

self.ingredients = ingredients

@classmethod

def from_fridge(cls, fridge):

return cls(fridge.get_cheese() + fridge.get_vegetables())

调用静态类:如果你把一个静态方法拆分成多个静态方法,除非你使用类方法,否则你还是得硬编码类名。使用这种方式声明方法,Pizza类名明永远都不会在被直接引用,继承和方法覆盖都可以完美的工作。

Python

class Pizza(object):

def __init__(self, radius, height):

self.radius = radius

self.height = height

@staticmethod

def compute_area(radius):

return math.pi * (radius ** 2)

@classmethod

def compute_volume(cls, height, radius):

return height * cls.compute_area(radius)

def get_volume(self):

return self.compute_volume(self.height, self.radius)

抽象方法

抽象方法是定义在基类中的一种方法,它没有提供任何实现,类似于Java中接口(Interface)里面的方法。

在Python中实现抽象方法最简单地方式是:

Python

class Pizza(object):

def get_radius(self):

raise NotImplementedError

任何继承自_Pizza的类必须覆盖实现方法get_radius,否则会抛出异常。

这种抽象方法的实现有它的弊端,如果你写一个类继承Pizza,但是忘记实现get_radius,异常只有在你真正使用的时候才会抛出来。

Python

Pizza()

__main__.Pizza object at 0x7fb747353d90

Pizza().get_radius()

Traceback (most recent call last):

File "stdin", line 1, in module

File "stdin", line 3, in get_radius

NotImplementedError

还有一种方式可以让错误更早的触发,使用Python提供的abc模块,对象被初始化之后就可以抛出异常:

Python

import abc

class BasePizza(object):

__metaclass__ = abc.ABCMeta

@abc.abstractmethod

def get_radius(self):

"""Method that should do something."""

使用abc后,当你尝试初始化BasePizza或者任何子类的时候立马就会得到一个TypeError,而无需等到真正调用get_radius的时候才发现异常。

Python

BasePizza()

Traceback (most recent call last):

File "stdin", line 1, in module

TypeError: Can't instantiate abstract class BasePizza with abstract methods get_radius

混合静态方法、类方法、抽象方法

当你开始构建类和继承结构时,混合使用这些装饰器的时候到了,所以这里列出了一些技巧。

记住,声明一个抽象的方法,不会固定方法的原型,这就意味着虽然你必须实现它,但是我可以用任何参数列表来实现:

Python

import abc

class BasePizza(object):

__metaclass__ = abc.ABCMeta

@abc.abstractmethod

def get_ingredients(self):

"""Returns the ingredient list."""

class Calzone(BasePizza):

def get_ingredients(self, with_egg=False):

egg = Egg() if with_egg else None

return self.ingredients + egg

这样是允许的,因为Calzone满足BasePizza对象所定义的接口需求。同样我们也可以用一个类方法或静态方法来实现:

Python

import abc

class BasePizza(object):

__metaclass__ = abc.ABCMeta

@abc.abstractmethod

def get_ingredients(self):

"""Returns the ingredient list."""

class DietPizza(BasePizza):

@staticmethod

def get_ingredients():

return None

这同样是正确的,因为它遵循抽象类BasePizza设定的契约。事实上get_ingredients方法并不需要知道返回结果是什么,结果是实现细节,不是契约条件。

因此,你不能强制抽象方法的实现是一个常规方法、或者是类方法还是静态方法,也没什么可争论的。从Python3开始(在Python2中不能如你期待的运行,见issue5867),在abstractmethod方法上面使用@staticmethod和@classmethod装饰器成为可能。

Python

import abc

class BasePizza(object):

__metaclass__ = abc.ABCMeta

ingredient = ['cheese']

@classmethod

@abc.abstractmethod

def get_ingredients(cls):

"""Returns the ingredient list."""

return cls.ingredients

别误会了,如果你认为它会强制子类作为一个类方法来实现get_ingredients那你就错了,它仅仅表示你实现的get_ingredients在BasePizza中是一个类方法。

可以在抽象方法中做代码的实现?没错,Python与Java接口中的方法相反,你可以在抽象方法编写实现代码通过super()来调用它。(译注:在Java8中,接口也提供的默认方法,允许在接口中写方法的实现)

Python

import abc

class BasePizza(object):

__metaclass__ = abc.ABCMeta

default_ingredients = ['cheese']

@classmethod

@abc.abstractmethod

def get_ingredients(cls):

"""Returns the ingredient list."""

return cls.default_ingredients

class DietPizza(BasePizza):

def get_ingredients(self):

return ['egg'] + super(DietPizza, self).get_ingredients()

这个例子中,你构建的每个pizza都通过继承BasePizza的方式,你不得不覆盖get_ingredients方法,但是能够使用默认机制通过super()来获取ingredient列表。

python的lambda函数是什么?

Python——Lambda表达式是一个匿名函数,Lambda 表达式基于数学中的lambda演算得名,直接对应于其中的 lambda 抽象,是一个匿名函数,即没有函数名的函数。

Python由荷兰数学和计算机科学研究学会的Guido van Rossum 于1990 年代初设计,作为一门叫做ABC语言的替代品。Python提供了高效的高级数据结构,还能简单有效地面向对象编程。

Python语法和动态类型,以及解释型语言的本质,使它成为多数平台上写脚本和快速开发应用的编程语言,随着版本的不断更新和语言新功能的添加,逐渐被用于独立的、大型项目的开发。

python的发展历程:

自从20世纪90年代初Python语言诞生至今,它已被逐渐广泛应用于系统管理任务的处理和Web编程。

Python的创始人为荷兰人吉多·范罗苏姆。1989年圣诞节期间,在阿姆斯特丹,Guido为了打发圣诞节的无趣,决心开发一个新的脚本解释程序,作为ABC语言的一种继承。之所以选中Python(作为该编程语言的名字,是取自英国20世纪70年代首播的电视喜剧《蒙提·派森的飞行马戏团》。

ABC是由Guido参加设计的一种教学语言。就Guido本人看来,ABC这种语言非常优美和强大,是专门为非专业程序员设计的。但是ABC语言并没有成功,究其原因,Guido认为是其非开放造成的。Guido决心在Python中避免这一错误。同时,他还想实现在ABC中闪现过但未曾实现的东西。

如何获取python编程基础及应用实验教程的实验文件

在 Python 中创建一个类及其对象

在 Python 中创建一个空类

在 Python 中使用 Type 创建类

在 Python 中创建和调用类的方法

使用 __init__() 方法为数据属性赋值

在 Python 中更新对象属性

在 Python 中删除对象属性和对象

在 Python 中检查和比较对象的类型

在Python中将对象的所有属性复制到另一个对象

在 Python 中迭代对象属性

在 Python 中打印对象的所有属性

在python中在运行时创建类的数据属性

在函数中将对象的实例作为参数传递

在 Python 中创建和使用自定义 Self 参数

使用self参数来维护对象的状态

在 Python 中创建和使用静态类变量

在 Python 中的一个函数上使用多个装饰器

在 Python 中的方法中同时访问 cls 和 self

从装饰器访问实例方法的类

使用给定的装饰器获取 Python 类的所有方法

装饰一个 class

将类字段作为参数传递给类方法上的装饰器

在 Python 中创建多个传入参数列表的类变量

Python 中的 wraps 装饰器

使用可选参数构建装饰器

在 Python 中将参数传递给装饰器

@property 装饰器

类和函数的装饰器

Python 中带参数和返回值的装饰器

Python 使用参数 wraps 装饰器

Python 装饰器获取类名

简单装饰器示例

在 Python 中使用 print() 打印类的实例

在 Python 中的类中将装饰器定义为方法

获取在 Python 中修饰的给定类的所有方法

带参数和不带参数的 Python 装饰器

Python 中带有 self 参数的类方法装饰器

在 Python 中的另一个类中使用隐藏的装饰器

装饰器内部的 self 对象

在 Python 中将多个装饰器应用于单个函数

Python 装饰器获取类实例

__init__ 和 __call__ 有什么区别

在 Python 中使用 __new__ 和 __init__

Python 中的迭代重载方法

在 Python 中使用迭代器反转字符串

Python 中 __reversed__ 魔术方法

Python 中的 __getitem__ 和 __setitem__

在 Python 中使用 __getattr__ 和 __setattr__ 进行属性赋值

什么是 __del__ 方法以及如何调用它

创建类的私有成员

一个 Python 封装的例子

一个 Python 组合的例子

一个Python聚合的例子

Python 中的单级、多级和多级继承

在 Python 中获取一个类的父类

Python 中的多态性

访问 Child 类中的私有成员

Python 中的抽象类

创建一个抽象类来覆盖 Python 中的默认构造函数

使一个抽象类继承另一个抽象类

Python 中的 super 是做什么的

super() 如何在多重继承中与 __init__() 方法一起工作

将 super 与类方法一起使用

mro 是做什么的

Python 中的元类是什么

元类的具体案例

在 Python 中使用元类的单例类

@staticmethod 和 @classmethod 有什么区别

Python 中的装饰器是什么

制作函数装饰器链


网站标题:python实验抽象函数的简单介绍
当前地址:http://cqcxhl.cn/article/dogocop.html

其他资讯

在线咨询
服务热线
服务热线:028-86922220
TOP