导航:首页 > 编程语言 > pythonunbound

pythonunbound

发布时间:2023-06-05 08:16:17

‘壹’ python如何调用自定义类中的函数

你好:
你要在自定义的函数里面的第一个参数设置为:
self
这是python约定的;
调用的时候可以不用管它,它相当于this!

‘贰’ 如何在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 <mole>
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 <mole>
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 <mole>
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中可以直接用类调用方法吗

这里先肯定的回答一下:可以

python里方法在类中是作为类的属性的,在解释之前,这边先给个例子

>>>classPizza(object):
...radius=42
...def__init__(self,size=10):
...self.size=size
...defget_size(self):
...returnself.size
...@staticmethod
...defmix_ingredients(x,y):
...returnx+y
...defcook(self):
...returnself.mix_ingredients(self.cheese,self.vegetables)
...@classmethod
...defget_radius(cls):
...returncls.radius
>>>Pizza.get_size
<unboundmethodPizza.get_size>
>>>Pizza.get_size()
Traceback(mostrecentcalllast):
File"<stdin>",line1,in<mole>
TypeError:unboundmethodget_size()(gotnothinginstead)
>>>Pizza.get_size(Pizza(42))
42
>>>Pizza(42).get_size
<boundmethodPizza.get_sizeof<__main__.Pizzaobjectat0x7f3138827910>>
>>>Pizza(42).get_size()
42
>>>m=Pizza(42).get_size
>>>m()
42
>>>m=Pizza(42).get_size
>>>m.__self__
<__main__.Pizzaobjectat0x7f3138827910>
>>>m==m.__self__.get_size
True
>>>Pizza().cookisPizza().cook
False
>>>Pizza().mix_ingredientsisPizza.mix_ingredients
True
>>>Pizza().mix_ingredientsisPizza().mix_ingredients
True
>>>Pizza.get_radius
<boundmethodtype.get_radiusof<class'__main__.Pizza'>>
>>>Pizza().get_radius
<boundmethodtype.get_radiusof<class'__main__.Pizza'>>
>>>Pizza.get_radiusisPizza().get_radius
True
>>>Pizza.get_radius()
42

在上面的例子中可以看出python中类有三种方法,分别是类方法,静态方法,实例方法。而能让类只接调用的只有类方法,或通过一些小技巧,类也可以调用实例方法如上面例子中的调用

>>>Pizza.get_size(Pizza(42))
42

这边顺便说明下这三中方法的区别

1类方法的特点是类方法不属于任何该类的对象,只属于类本身

2类的静态方法类似于全局函数,因为静态方法既没有实例方法的self参数也没有类方法的cls参数,谁都可以调用

3.实例方法只属于实例,是实例化的对象才能调用

‘肆’ python中怎样判断一个文件的类型

这种方法叫做调用父类的未绑定的构造方法。在调用一个实例的方法时,该方法的self参数会被自动绑定到实例上(称为绑定方法)。
但如果直接调用类的方法(比如A.__init),那么就没有实例会被绑定。这样就可以自由的提供需要的self参数,这种方法称为未绑定unbound方法。

‘伍’ Python中为什么推荐使用isinstance来进行类型判断

Python在定义变量的时候不用指明具体的的类型,解释器会在运行的时候会自动检查 变量的类型,并根据需要进行隐式的类型转化。因为Python是动态语言,所以一般情 况下是不推荐进行类型转化的。比如"+"操作时,如果加号两边是数据就进行加法操 作,如果两边是字符串就进行字符串连接操作,如果两边是列表就进行合并操作,甚 至可以进行复数的运算。解释器会在运行时根据两边的变量的类型调用不同的内部方法。 当加号两边的变量类型不一样的时候,又不能进行类型转化,就会抛出TypeError的异常。
但是在实际的开发中,为了提高代码的健壮性,我们还是需要进行类型检查的。而进行 类型检查首先想到的就是用type(),比如使用type判断一个int类型。
import typesif type(1) is types.Integer: print('1是int类型')else: print('1不是int类型')

上面的程序会输出:1是int类型
我们在types中可以找到一些常用的类型,在2.7.6中显示的结果:
types.BooleanType # bool类型types.BufferType # buffer类型types.BuiltinFunctionType # 内建函数,比如len()types.BuiltinMethodType # 内建方法,指的是类中的方法types.ClassType # 类类型types.CodeType # 代码块类型types.ComplexType # 复数类型types.DictProxyType # 字典代理类型types.DictType # 字典类型types.DictionaryType # 字典备用的类型types.EllipsisTypetypes.FileType # 文件类型types.FloatType # 浮点类型types.FrameTypetypes.FunctionType # 函数类型types.GeneratorType
types.GetSetDescriptorTypetypes.InstanceType # 实例类型types.IntType # int类型types.LambdaType # lambda类型types.ListType # 列表类型types.LongType # long类型types.MemberDescriptorTypetypes.MethodType # 方法类型types.MoleType # mole类型types.NoneType # None类型types.NotImplementedTypetypes.ObjectType # object类型types.SliceTypehtypes.StringType # 字符串类型types.StringTypes
types.TracebackType
types.TupleType # 元组类型types.TypeType # 类型本身types.UnboundMethodTypetypes.UnicodeType
types.XRangeType

在Python 3中,类型已经明显减少了很多
types.BuiltinFunctionType
types.BuiltinMethodType
types.CodeType
types.DynamicClassAttribute
types.FrameType
types.FunctionType
types.GeneratorType
types.GetSetDescriptorType
types.LambdaType
types.MappingProxyType
types.MemberDescriptorType
types.MethodType
types.MoleType
types.SimpleNamespace
types.TracebackType
types.new_class
types.prepare_class

但是我们并不推荐使用type来进行类型检查,之所以把这些类型列出来,也是为了扩展知识 面。那为什么不推荐使用type进行类型检查呢?我们来看一下下面的例子。
import typesclass UserInt(int): def __init__(self, val=0): self.val = int(val)i = 1n = UserInt(2)print(type(i) is type(n))

上面的代码输出:False
这就说明i和n的类型是不一样的,而实际上UserInt是继承自int的,所以这个判断是存在问题的, 当我们对Python内建类型进行扩展的时候,type返回的结果就不够准确了。我们再看一个例子。
class A(): passclass B(): passa = A()b = B()print(type(a) is type(b))

代码的输出结果: True
type比较的结果a和b的类型是一样的,结果明显是不准确的。这种古典类的实例,type返回的结果都 是一样的,而这样的结果不是我们想要的。对于内建的基本类型来说,使用tpye来检查是没有问题的, 可是当应用到其他场合的时候,type就显得不可靠了。这个时候我们就需要使用isinstance来进行类型 检查。
isinstance(object, classinfo)

object表示实例,classinfo可以是直接或间接类名、基本类型或者有它们组成的元组。
>>> isinstance(2, float)
False
>>> isinstance('a', (str, unicode))
True
>>> isinstance((2, 3), (str, list, tuple))
True

‘陆’ 本人python新手,现在在看python基础教程,这几天敲了一下后面的项目5,出现了很奇怪的错误,大神帮看看

Room.add(self)这一句改成
Room().add()
当然,只是一个比喻,具体怎么样改,还要看你的程序。
Room是一个类,除非它有特殊的方法。否则不能使用Room.add这样的方法,在python不让。

你可以先实例化Room,比如Room(),然后在这个实例上就可以使用权Room().add()

此外你Room.add(self)里的self显然不是Room实例,否则也许能成功。

‘柒’ Python中静态方法和类方法的区别

面相对象程序设计中,类方法和静态方法是经常用到的两个术语。
逻辑上讲:类方法是只能由类名调用;静态方法可以由类名或对象名进行调用。
在C++中,静态方法与类方法逻辑上是等价的,只有一个概念,不会混淆。
而在python中,方法分为三类实例方法、类方法、静态方法。代码如下:
class Test(object):
def InstanceFun(self):
print("InstanceFun");
print(self);
@classmethod
def ClassFun(cls):
print("ClassFun");
print(cls);
@staticmethod
def StaticFun():
print("StaticFun");
t = Test();
t.InstanceFun();# 输出InstanceFun,打印对象内存地址“”
Test.ClassFun(); # 输出ClassFun,打印类位置
Test.StaticFun(); # 输出StaticFun
t.StaticFun(); # 输出StaticFun
t.ClassFun(); # 输出ClassFun,打印类位置
Test.InstanceFun(); # 错误,TypeError: unbound method instanceFun() must be called with Test instance as first argument

Test.InstanceFun(t); # 输出InstanceFun,打印对象内存地址“”
t.ClassFun(Test); # 错误 classFun() takes exactly 1 argument (2 given)
可以看到,在PYTHON中,两种方法的主要区别在于参数。实例方法隐含的参数为类实例self,而类方法隐含的参数为类本身cls。
静态方法无隐含参数,主要为了类实例也可以直接调用静态方法。

所以逻辑上类方法应当只被类调用,实例方法实例调用,静态方法两者都能调用。主要区别在于参数传递上的区别,实例方法悄悄传递的是self引用作为参数,而类方法悄悄传递的是cls引用作为参数。
Python实现了一定的灵活性使得类方法和静态方法,都能够被实例和类二者调用

阅读全文

与pythonunbound相关的资料

热点内容
结对程序员 浏览:762
使用过的苹果手机怎么同步app 浏览:344
phpcookie无效 浏览:954
python可以搜数学答案 浏览:706
均线衍生指标源码设置 浏览:496
做精一张图pdf 浏览:851
编程培训小朋友 浏览:787
巴克球制作解压 浏览:851
测量参数时接单片机的 浏览:116
手机音乐添加文件夹 浏览:546
百度智能云b18怎么删除app 浏览:968
单片机中为什么显示找不到头文件 浏览:151
iisweb服务器如何重启 浏览:838
微信没有适配方舟编译器 浏览:81
箍筋加密区梁的净高 浏览:889
samp如何加入外国服务器 浏览:895
保鲜膜解压教学视频 浏览:983
台达plc编程通讯管理软件 浏览:407
优优pdf 浏览:801
程序员职业穿搭 浏览:257