基本上可以看作数据以及由一系列可以存取、操作这些数据的方法所组成的集合
具有以下优点——
不知道变量所引用的对象类型是什么,还能对它进行操作,因为它会根据对象(或类)的类型的不同而采取不同的行为
from random import choice #choice会从参数(序列)中随机取出一个元素并返回
x = choice( [ "hello, world", [1, 2, 'e','e', 4] ] )
#序列里既有字符串又有列表,那么x是字符串还是列表呢?程序会自行判断
x
向程序的其他部分隐藏对象的具体实现细节
抽象地处理程序组件而不关注实现细节
多态和封装的概念区分——
多态针对的是对象的类
封装针对的是对象的构建细节
A类从B类继承方法,在A类上调用方法时,程序会自动从B类调用相应的方法
所有属于同一个类的对象,成为类的实例(instance)
大类以下细分为若干小类,小类称为大类的子类,大类成为小类的超类
python中习惯用首字母大写的单词描述一个类
方法:(更专业的叫法是“绑定方法”)与函数不同,它是绑定到某个特定的类上的
#新式类的语法中,在模块或脚本的开头加入以下赋值语句
__metaclass__ = type
class Person: #用class语句创建类,Person即是类名
def setName(self, name): #类的方法定义跟函数定义形式一致,而且这里的self参数表示的是属于类的实例自身,接受实参时实际上是不包括self的
self.name = name #设置对象的name属性
def getName(self):
return self.name
def greet(self):
print "Hello, world! I'm %s" % self.name
#方法是类内的函数,第一个参数总为self
foo = Person() #foo是Person类的一个实例
foo.setName("Zk")
foo.getName()
foo.greet()
#以上语句也能写成“类.方法(参数)”的形式
#这里的参数self需要指定为实例foo
Person.greet(foo)
#用变量引用绑定方法
foogreet = foo.greet #注意此处不能有括号
foogreet()
在其他一些语言中,能够将对象的方法和特性变为私有,从外部无法访问
但是python不存在私有化功能
不过却有一种“名字变换术”
class Secretive:
def __inaccessible(self): #方法名前加上双下划线,外部将不能访问这个方法
print "Bet you can't see me..."
def accessible(self):
print "The secret message is: "
self.__inaccessible() #从内部却可以访问
s = Secretive()
s.__inaccessiable() #外部不能访问
s.accessible() #内部可以访问
#事实上,以双下划线为前缀的方法名在内部会自动翻译为 (单下划线_)+“类名”+“带双下划线的方法名”
#也就是说,我们依旧能够访问这个方法
s._Secretive__inaccessible()
如果不需要使用这种方法,又不想让其他对象访问内部数据,可以使用单下划线
毕竟“from module import *”语句是不会导入以单下划线为前缀的名字的
class MemberCounter():
members = 0 #为类定义一个变量
def init(self):
MemberCounter.members += 1
m1 = MemberCounter()
m1.init()
MemberCounter.members #通过“类.变量”的形式就可以从外部访问类内部的变量
m2 = MemberCounter()
m2.init()
MemberCounter.members
#也可以通过实例访问这个变量
m1.members
#如果我们给对象设置一个同名变量呢?
m1.members = 'Two'
m1.members #对象m1内的变量屏蔽了类的变量
m2.members #对象m2内并没有同名变量
MemberCounter.members
#对象命名空间是类命名空间的子空间
#对象命名空间内的同名变量会屏蔽掉类命名空间的变量
#“对象内变量 和 类内变量” 的关系类似于“局部变量 和 全局变量”的关系
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): #SPAMFliter是Filter的子类
def init(self): #重写init方法
self.blocked = ['SPAM']
#此处Filter是序列过滤的通用类
#SPAMFilter是这个通用类下的一种情况,一个子类,它继承了超类的方法,但是我们重写了init方法
s = SPAMFilter()
s.init()
s.filter(['SPAM', 'SPAM', 'SPAM', 'SPAM', 'eggs', 'bacon', 'SPAM'])
issubclass函数:查看一个类是不是另一个类的子类
isinstance函数:查看一个对象是不是一个类的实例(应少用)
__bases__特性:查看类的超类(们)
__class__特性:查看对象的类
issubclass(SPAMFilter, Filter) #第一个参数是子类,第二个参数是超类,则返回True
issubclass(Filter, SPAMFilter)
SPAMFilter.__bases__
Filter.__bases__
isinstance(s, SPAMFilter) #第一个参数是对象,第二个参数是类,返回布尔值
s.__class__
#新式类的对象还可以使用type函数
type(s)
如非特别熟悉,否则应该尽量避免多重继承
即公开的方法和特性
#hasattr函数:检查方法是否存在,返回布尔值
hasattr(SPAMFilter, 'filter') #第一个参数为类名或对象名,第二个参数为特性名或方法名(必须为字符串)
#getattr函数:尝试访问特性,如果存在,返回该特性
getattr(s, 'filter', None) #第一个参数为类名或对象名,第二个参数为特性名或方法名(必须为字符串),第三个参数为默认值
#如果不存在,返回指定的默认值
getattr(s, 'aaa', 'N/A')
#如果没有设置默认值,程序出错
getattr(s, 'aaa')
#getattr函数可以配合callable函数,判断方法能否被调用
callable( getattr(s,'filter', None) )
callable( getattr(s, 'aaa', None) )
#但是callable在python3中已经不能使用
#我们可以检查__call__来代替
hasattr(getattr(s, 'filter', None) , '__call__')
hasattr(pow, '__call__') #也可以是函数
#setattr函数:为对象设置特性
setattr(s, 'name', 'Zk') #第一个参数是对象,第二个参数是特性名,第三个参数是特性值
s.name
#可以通过访问__dict__特性查看对象所有存储值
s.__dict__