Python中的抽象

判断函数是否可调用

python2.x版本通过
callable(x)
3.x版本使用表达式
hasattr(func,__call__)

函数的参数

关键字参数和默认值

def hello_1(greeting,name):
    print greeting,name

hello_1("hello","Saint")

定义了一个hello函数,它有两个参数,这里参数的顺序很重要。但是如果参数很多的情况下,难免无法保证全部输对,这时候可以提供参数的名字:

hello_1(name="Saint",greeting="nice to meet you,")

如上,只要参数名称提供对了,可以不用考虑顺序。

关键参数还可以设置默认值

def hello_2(greeting="hello", name="jack"):
    print greeting, name

hello_2()
hello_2("nice to meet you")
hello_2(name="saint")

输出:

hello jack
nice to meet you jack
hello saint

上面的3种用法都是可以的。

收集参数

可以传入任意数量的参数:

def print_params(*params):
    print params

print_params("Test") #('Test',)
print_params(1,2,3) #(1, 2, 3)

这个函数只定义了一参数,前面加了个*号,类似于Java中的...*号的作用是收集参数,从输出可以看出python是用元组来保存这些参数的。

还有一个能处理关键字参数用法:

def print_params_2(**params):
    print params

print_params_2(x=1,y=2,z=3) #{'y': 2, 'x': 1, 'z': 3}

它打印的是字典而不是元组

收集参数的逆过程

所谓逆过程是指,不是在方法参数定义中使用*号,而是在调用方法的入参中使用。

def add(x,y):
    return x+y

params = (1,2)
print add(*params) #3

这个add方法需要两个参数,可以在调用时在元组params左边添加一个*号。实现将元组内的两个元素相加。

可以使用同样的技术来处理字典-使用**运算符。

可以这样使用

params = {'name':'jack','greeting':'nice to meet you'}
hello_2(**params) #nice to meet you jack

*号对应元组,**号对应字典

函数式编程

函数可以分配给变量、作为参数传递以及从其他函数返回。

In [5]: import functools                                                                                     
In [8]: def func(x): 
   ...:     return x.isalnum()  # 检测字符串是否由字母和数字组成
   ...:                                                                                                      
In [9]: seq = ['foo','x41','?!','***']                                                                       
In [10]: filter(func,seq)                                                                                    
Out[10]: <filter at 0x7fc99d586b70>
In [12]: list(filter(func,seq))                                                                              
Out[12]: ['foo', 'x41']

(python3)

这里函数func作为参数传递到了filter()函数。

创建自己的类

__metaclass__ = type #使用新式类

class Person:
    def setName(self,name):
        self.name = name
    def getName(self):
        return self.name
    def greet(self):
        print "Hello,world! I'm %s." % self.name

注意,这里和Java中不同的是,name属性之前没有定义self.name = name将参数中的name赋值到属性name,保持着python中属性不用定义的特性。

使用方法:

foo = Person()
bar = Person()
foo.setName("Saint")
bar.setName("Jack")

foo.greet()#Hello,world! I'm Saint.
bar.greet()#Hello,world! I'm Jack. 

在setName和greet函数里面有一个self,这里的self类似于Java中的this,不过Java中的this是隐式的(即不需要在函数参数中写明)。

还可以通过.号来访问变量:

foo.name = "Mikey"
foo.greet()

相当于name是公有域。

函数和方法

方法和函数的区别是self参数。方法(或称为绑定方法)将它们的第一个参数绑定到所属的实例上。

python中的方法一般指定义在对象中的method

私有化

Python不直接支持私有方式,但可以通过一些小技巧达到私有属性的效果。

在方法或属性的名字前面加上双下划线__可将方法或属性变为私有

class Secretive:
    def __inaccessible(self):
        print "Bet you cant see me..."
    def accessible(self):
        print "The secret message is:"
        self.__inaccessible()

访问一下看:

s = Secretive()
s.__inaccessible()#! AttributeError: 'Secretive' object has no attribute '__inaccessible'

上面尝试访问这个方法会报错,看起来像是其他语言中的标准私有方法。

类的内部定义中,所有以双下划线开始的名称都被翻译成前面加上单下划线和类名的形式:

if __name__ == '__main__':
    s = Secretive()
    s._Secretive__inaccessible() # Bet you cant see me...

Java中也有这种类似的特例,能通过反射访问私有属性和方法。权且通过这种方式来理解就好了

推荐使用单下划线命名私有属性或方法。

类的命名空间

所有位于class语句中的代码都在类命名空间中执行。这个命名空间可由类内所有成员访问。

class MemberCounter:
    members = 0
    def init(self):
        MemberCounter.members += 1

m1 = MemberCounter()
m1.init()
print MemberCounter.members #1

m2 = MemberCounter()
m2.init()
print MemberCounter.members #2

上面的代码中在类作用域内定义了一个所有成员(实例)可以访问的变量,类似于Java中的类变量。注意每次都是通过类名去访问的。

如果实例中重绑定members:

m1.members = 'Hello'
print m1.members # Hello
print m2.members # 2

新members值被写到了m1的特性中,屏蔽了类范围内的变量。

指定超类

将其他类名写在class语句后的圆括号内可以指定超类(父类):

class Filter:
    def init(self):
        self.blocked = []
    def filter(self,sequence):
        return [ x for x in sequence if x not in self.blocked]

class SPAMFilter(Filter):
    def init(self): #重写Filter超类中的init方法
        self.blocked = ['SPAM']
s = SPAMFilter()
s.init()
print s.filter(['SPAM','SPAM','SPAM','SPAM','SPAM','SPAM','eggs','bacon','SPAM'])

打印

['eggs', 'bacon']

其中SPAMFilter的filter方法继承了父类的方法。

检查继承

使用内建的issubclass函数来查看一个类是否是另一个类的子类:

print issubclass(SPAMFilter,Filter) # True
s = SPAMFilter() # 检查一个对象是否是另一个类的实例
print isinstance(s,SPAMFilter) # True

多个超类

class Calculator:
    def caculate(self, expression):
        self._value = eval(expression)

class Talker:
    def talk(self):
        print 'Hi, my value is ' , self._value

class TalingCalculator(Calculator,Talker):
    pass

if __name__ == '__main__':
    tc = TalingCalculator()
    tc.caculate('1+2*3')
    tc.talk() # Hi, my value is  7

python中允许多重继承,但是有个注意的地方,如果一个方法从多个超类继承(超类中都有相同名字的方法),那么必须要注意一下超类的顺序,先继承的类中的方法会重写后继承的类中的方法。

你可能感兴趣的:(python)