python函数隐式调用的简单介绍

Python 数据模型

Python 风格的关键完全体现在 Python 的数据模型上,数据模型所描述的 API ,为使用最地道的语言特性来构建开发者自己的对象提供了工具。

10年积累的成都网站设计、成都做网站经验,可以快速应对客户对网站的新想法和需求。提供各种问题对应的解决方案。让选择我们的客户得到更好、更有力的网络服务。我虽然不认识你,你也不认识我。但先网站设计后付款的网站建设流程,更有土默特左旗免费网站建设让你可以放心的选择与我们合作。

当 Python 解析器遇到特殊句法时,会使用特殊方法去激活一些基本的对象操作。特殊方法以双下划线开头,以双下划线结尾。如: obj[key] 的背后就是 __getitem__ 方法。魔术方法是特殊方法的昵称,特殊方法也叫双下方法。

使用 __getitem__ 和 __len__ 创建一摞有序的纸牌:

上面的例子,使用 collections.namedtuple 构建了一个简单的类来表示一张纸牌, namedtuple 用以构建只有少数属性但没有方法的类。

我们自定义的 FrenchDeck 类可以像任何 python 标准集合类型一样使用 len() 函数,查看一叠牌有多少张:

也可以像列表一样,使用位置索引, d[i] 将调用 __getitem__ 方法:

也可以使用标准库模块提供的 random.choice 方法,从序列中随机选取一个元素。下面,我们如随机取出一张纸牌:

现在我们已经体会到通过 python 特殊方法,来使用 Python 数据模型的 2 个好处:

因为 __getitem__ 方法把 [] 操作交给了 self.cards 列表,所以我们的 FrenchDeck 实例自动支持切片:

仅仅实现了 __getitem__ 方法,这一摞牌即变得可迭代:

运行结果:

也可以直接调用内置的 reversed 函数,反向迭代 FrenchDeck 实例:

运行结果:

迭代通常是隐式的,比如一个集合类型没有实现 __contains__ 方法,那么 in 运算符就会按顺序做一次迭代搜索。

因此, in 运算符可以用在我们的 FrenchDeck 实例上,因为它是可迭代的:

FrenchDeck 还可以使用 Python 标准库中的 sorted 函数,实现排序:

首先定义一个排序依据的函数:

优先按 rank 的大小排序,rank 相同时则比较 suit 的值:

运行结果:

优先按 suit 的大小排序,suit 相同时则比较 rank 的值:

运行结果:

按照目前的设计,FrenchDeck 还不支持洗牌,因为它是不可变的:

shuffle 函数要调换集合中元素的位置,而 FrenchDeck 只实现了不可变的序列协议,可变的序列还必须提供 __setitem__ 方法:

洗牌:

没有任何的返回值,可见 random.shuffle 就地修改了可变序列 d 。为便于观察结果,我们定义输入的输出函数:

运行结果:

每次洗牌,都是一个随机的序列:

首先明确一点,特殊方法的存在是为了被 Python 解析器调用的,例如:我们不会使用 obj.__len__() 这种写法,而是 len(obj) 。在执行 len(obj) 时,如果 obj 是一个自定义类的对象,那么 Python 会自己去调用我们实现的 __len__ 方法。

对于 Python 内置的数据类型,比如列表、字符串、字节序列等,那么 CPython 会抄个近路, __len__ 实际上会返回 PyVarObject 里的 ob_size 属性,这是因为直接读取属性比调用一个方法要快得多。

很多时候,特殊方法的调用是隐式的,比如 for i in x: 这个语句其实是调用 iter(x) ,而这个函数的背后是 x.__iter__() 方法。

通过内置函数如来使用特殊方法是最好的选择。这些内置函数不仅会调用这些方法,通常还提供额外的好处,对于内置类型来说,它们的速度更快。

下面,我们通过定义一个简单的二维向量类,再来体会一下 Python 特殊方法的美妙:

使用 Vector 类,就像使用 Python 内置的数据类型一样简单:

Python中的返回值问题!!!

首先,代码有误,你想调用的应该是

sorted([4,3,2,1])

reversed([4,3,2,1])

然后,你所说的reversed的返回值类型也不正确。

sorted返回的是list,reversed返回的是iterator。

list你应该很熟悉了。iterator和list是完全不同的东西。简单的说iterator只是提供一个接口,每次迭代可以产生一个值,到没有值为止。iterator在很多语言里面都有实现。在python里面主要用在for循环和list comprehension。

iterator和list/tuple/dict/set等容器的关系:

1.python内置的容器类几乎都实现了iterator接口。

显式获取某个容器的iterator可以调用iter函数:

l = [1,2,3,4]

i = iter(l)

//现在i就是一个list iterator。可以用来遍历l这个list.

i.next() # 1

i.next() # 2

//每一个iterator都必须实现next方法。并且在没有元素时抛出StopIteration异常。

在for语句和list comprehension中,都是隐式调用了这个函数。所以可以直接

for obj in some_container:

pass

2.某些容器可以通过iterator进行初始化,比如list

l = [1,2,3,4]

i = iter(l)

l2 = list(i)

最后,没有列表和列表对象这种说法。这两者一般都是指列表对象(instance of the type list)。如果你是想说列表类(the list type)本身,可以这样得到:

type([])

或者

[].__class__

python函数的返回值?

题主你好,

关键点在于函数如果没有明确使用return关键字指定函数的返回值,则默认返回值是none.

-----

所以temp = hello()这句的理解就是: 执行hello()这个函数, 并且把函数的返回值赋给变量temp, 但hello()函数中没有return语句, 所以hello()函数的返回值为默认的none.

-----

题主还可以在hello()函数最后加一个: return 123

然后再行一下看看,就明白了.

=====

希望可以帮到题主, 欢迎追问.

python 怎么样隐式函数调用

最常用的是在类定义的方法,给一个property的装饰器,可以安装调用属性的方式调用

如何解决python2不能隐式继承

继承是所有开发语言的必修内容,而本文写的只是Python继承中的特殊之处,关于继承概念及内容可以自行百度(不装B,感觉百度挺好的)1.构造函数:

要说继承,先要说一下构造函数。Java要求是与类名相同并且无返回值,而Python则是强制要求命名为“__init__()”。

当创建类的对象时,会自动先调用构造函数,一般用于初始化。构造函数可以不写,那么程序会隐式自动增加一个空的构造函数。

2.继承写法:

(1).class 空格 类名称 括号内填写父类名 冒号具体写法如下class A:

def __init__(self):

pass

def print_class_name(self):

print "this is class A"

class B(A):

def __init__(self):

pass

if __name__ == "__main__":

class_b = B()

class_b.print_class_name()

上面代码首先定义了一个名为“A”的类,包含一个名为“print_class_name”的方法。然后,定义一个名为“B”的类,继承“A”,同时继承了“A”类的“print_class_name”的方法。

此时“A”类为“B”类的父类或者叫基类,“B”类是“A”类的子类,子类会继承父类的所有公共方法。

(2).意义:

一字记之曰“懒!”(感叹号不算字)我始终相信赖人才能推动科学进步。

言归正传,假如你要写一个老王类,包含年龄、性别等方法,后面还要写一个老王的儿子小王类,也有年龄、性别等方法?

class FatherWang:

def __init__(self, age=43, sex='man'):

self.a = age

self.s = sex

def age(self):

print self.a

def sex(self):

print self.s

class SonWang:

def __init__(self, age=13, sex='man'):

self.a = age

self.s = sex

def age(self):

print self.a

def sex(self):

print self.s

if __name__ == "__main__":

father = FatherWang(43, "man")

father.age()

father.sex()

son = SonWang(13, "man")

son.age()

son.sex()

你会发现两个类中有相同名称和功能的方法,这样写岂不是很重复很累?(尽管按键盘次数不算太多,我依然觉得很累)如果有继承就很好解决了。

class FatherWang:

def __init__(self, age=43, sex='man'):

self.a = age

self.s = sex

def age(self):

print self.a

def sex(self):

print self.s

class SonWang(FatherWang):

def __init__(self, age=13, sex='man'):

FatherWang.__init(age, sex)

if __name__ == "__main__":

father = FatherWang(43, "man")

father.age()

father.sex()

son = SonWang(13, "man")

son.age()

son.sex()

两者运行结果完全一样,但是使用继承方法却省了很多按键盘的次数。

3.经典类与新式类:

(1)经典类写法:

class A:

pass

(2)新式类写法:

class A(object):

pass

可以看出,新式类和经典类的区别在于,是否继承object这个基类。object是所有类的父类。所以之前不带“(object)”的写法,属于经典类写法,加上“(object)”就是新式类的写法。

(3).原因:这里我得吐槽一下Python的版本混乱。2.2版本之前只有经典类写法,这里有一个问题,代码如下?

class A:

pass

class B(object):

pass

a = A()

b = B()

print a.__class__

print type(a)

print "----------"

print b.__class__

print type(b)

结果为:

__main__.A

type 'instance'

----------

class '__main__.B'

class '__main__.B'

首先A类为经典类,B类为新式类。__class__属性和type()方法都是返回对象类型,那么问题来了,使用经典类的写法返回结果却不一致。因此在2.2版本之后出现了新式类来解决这个问题,自然,新式类和经典类还有更大的区别在后面说。另外在3.3版本中,无论使用哪种写法,python都会隐式的继承object,所以3.3版本不会再有经典类(在这里我只想问,早干什么去了!),但是鉴于3.3兼容性问题,貌似没有太多人用。

4.方法重写与方法重载

(1).方法重写:

class FatherWang:

def __init__(self, age=43, sex='man'):

self.a = age

self.s = sex

def age(self):

print self.a

def sex(self):

print self.s

def name(self):

print "Wang_yang"

class SonWang(FatherWang):

def __init__(self, age=13, sex='man'):

FatherWang.__init(age, sex)

def name(self):

print "Wang_xiaoming"

if __name__ == "__main__":

father = FatherWang(43, "man")

father.age()

father.sex()

father.name()

son = SonWang(13, "man")

son.age()

son.sex()

son.name()

比继承写法(2)中的代码相比,两个类分别多了同名的方法“name”,之前说过子类会继承父类的方法,那么这时候两个类有相同名字的方法,冲突了,怎么处理?

这个时候,就叫方法重写。可以理解为,子类的“name”方法把父类的“name”方法覆盖了,重新写了,所以调用子类的“name”方法时,会以子类的为准(尽管这种理解并不准确,但是可以很好解释“方法重写”这个名词,后面会讲到正确理解)。

注意下面的代码

class FatherWang:

def __init__(self, age=43, sex="man"):

self.a = age

self.s = sex

print "I am FatherWang"

def age(self):

print "Father age:"+str(self.a)

def sex(self):

print "Father sex:"+str(self.s)

class MotherLi:

def __init__(self, age=40, sex="woman"):

self.a = age

self.s = sex

print "I am MotherLi"

def age(self):

print "Mother age:"+str(self.a)

def sex(self):

print "Mother sex"+str(self.s)

class SonWang(FatherWang, MotherLi):

def __init__(self, age=13, sex="man"):

FatherWang.__init__(self, age, sex)

MotherLi.__init__(self, age, sex)

print "I am SonWang"

if __name__ == "__main__":

son = SonWang()

son.age()

son.sex()

执行结果:

I am FatherWang

I am MotherLi

I am SonWang

Father age:13

Father sex:man

在之前代码上稍作修改,另外增加了一个MotherLi的类,SonWang类继承了FatherWang类和MotherLi类。注意,这是经典类的写法。

首先,我们知道了python多继承的写法,就是在括号中上一个父类后面加个逗号,然后再写上下一个父类的名字:

class SonWang(FatherWang, MotherLi):

其次,FatherWang类和MotherLi类,都有名为age和sex方法,SonWang类为什么会继承FatherWang类的方法呢?那么把SonWang类的继承顺序改一下class SonWang(MotherLi, FatherWang):

就会发现继承的是MotherLi类的方法。

通过结果可知,是按照继承的顺序。

让我们把代码结构变得更发杂一些吧,我想会崩溃的,哈哈哈?

class Grandfather:

def __init__(self, age=73, sex="man"):

self.a = age

self.s = sex

print "I am Grandfather"

def age(self):

print "Grandfather age:"+str(self.a)

def sex(self):

print "Grandfather sex:"+str(self.s)

def Interesting(self):

print "Grandfather Interesting"

class Grandmother:

def __init__(self, age=70, sex="woman"):

self.a = age

self.s = sex

print "I am Grandmother"

def age(self):

print "Grandmother age:"+str(self.a)

def sex(self):

print "Grandmother sex:"+str(self.s)

def Interesting(self):

print "Grandmother Interesting"

class FatherWang(Grandfather, Grandmother):

def __init__(self, age=43, sex="man"):

self.a = age

self.s = sex

Grandfather.__init__(self, age, sex)

Grandmother.__init__(self, age, sex)

print "I am FatherWang"

def age(self):

print "Father age:"+str(self.a)

def sex(self):

print "Father sex:"+str(self.s)

class MotherLi(Grandfather, Grandmother):

def __init__(self, age=40, sex="woman"):

self.a = age

self.s = sex

Grandfather.__init__(self, age, sex)

Grandmother.__init__(self, age, sex)

print "I am MotherLi"

def age(self):

print "Mother age:"+str(self.a)

def sex(self):

print "Mother sex"+str(self.s)

def Interesting(self):

print "MotherLi Interesting"

class SonWang(FatherWang, MotherLi):

def __init__(self, age=13, sex="man"):

FatherWang.__init__(self, age, sex)

MotherLi.__init__(self, age, sex)

print "I am SonWang"

if __name__ == "__main__":

son = SonWang()

son.age()

son.sex()

son.Interesting()

执行结果:

I am Grandfather

I am Grandmother

I am FatherWang

I am Grandfather

I am Grandmother

I am MotherLi

I am SonWang

Father age:13

Father sex:man

Grandfather Interesting

话说,我自己都有点儿晕。简单来讲,就是儿子继承了老爸、老妈,然后老爸继承了爷爷、奶奶,妈妈继承了老爷、姥姥。(真是一大家子啊)通过执行结果可知,儿子类先找到老爸类,然后再找老爸类的第1个父类爷爷类,此时发现爷爷类没有父类了,那么执行初始化。然后还要继续找到老爸类的第2个父类奶奶类,此时发现奶奶类没有父类了,执行初始化。此时老爸类的所有父类都初始化完成,初始化自己。然后开始找妈妈类……那么为什么Interesting方法会使用爷爷类的呢?奶奶类、老爷类、姥姥类都有啊?首先儿子类没有Interesting方法,会先找第1个父类老爸类。发现老爸类也没有,再找老爸类的第1个父类,发现找到了,那么就直接调用不再往下找了。

结论:经典类的多继承,按照继承顺序查找。即,从左到右,从下到上的方式。注意,只有经典类是这样的!

(2).新式类的多继承:

class Grandfather(object):

def __init__(self, age=73, sex="man"):

self.a = age

self.s = sex

print "I am Grandfather"

def age(self):

print "Grandfather age:"+str(self.a)

def sex(self):

print "Grandfather sex:"+str(self.s)

def Interesting(self):

print "Grandfather Interesting"

class Grandmother(object):

def __init__(self, age=70, sex="woman"):

self.a = age

self.s = sex

print "I am Grandmother"

def age(self):

print "Grandmother age:"+str(self.a)

def sex(self):

print "Grandmother sex:"+str(self.s)

def Interesting(self):

print "Grandmother Interesting"

class FatherWang(Grandfather, Grandmother):

def __init__(self, age=43, sex="man"):

self.a = age

self.s = sex

Grandfather.__init__(self, age, sex)

Grandmother.__init__(self, age, sex)

print "I am FatherWang"

def age(self):

print "Father age:"+str(self.a)

def sex(self):

print "Father sex:"+str(self.s)

class MotherLi(Grandfather, Grandmother):

def __init__(self, age=40, sex="woman"):

self.a = age

self.s = sex

Grandfather.__init__(self, age, sex)

Grandmother.__init__(self, age, sex)

print "I am MotherLi"

def age(self):

print "Mother age:"+str(self.a)

def sex(self):

print "Mother sex"+str(self.s)

def Interesting(self):

print "MotherLi Interesting"

class SonWang(FatherWang, MotherLi):

def __init__(self, age=13, sex="man"):

FatherWang.__init__(self, age, sex)

MotherLi.__init__(self, age, sex)

print "I am SonWang"

if __name__ == "__main__":

son = SonWang()

son.age()

son.sex()

son.Interesting()

执行结果:

I am Grandfather

I am Grandmother

I am FatherWang

I am Grandfather

I am Grandmother

I am MotherLi

I am SonWang

Father age:13

Father sex:man

MotherLi Interesting


分享名称:python函数隐式调用的简单介绍
分享链接:http://myzitong.com/article/dodsphh.html