Hom's Blog


Python:类和对象object

类的一般知识

Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。用类作为抽象”模板”, 而创建机体的一个对象, 称之为实例(Instance).用来储存对象属性数据的称为属性, 而调用来进行针对对象的处理的关联函数,称之为方法.

定义一个类

# 定义一个普通类, 不进行继承
class ClassName(): 
	statement

# 定义一个继承于父类的类
# 可以多个父类
class ClassName(Parent1[,Parent2..]):
	statement

# 定义一个新式类,继承自object
class ClassName(object): 
	statement

# 使用type函数定义类
# parents是元组,继承的父类,第三个是字典,定义属性和方法
ClassName=type("ClassName",(parents),{"property/method":value})

定义类属性和方法

class ClassName():
	# 定义类内的属性 
	prop1=value1

	# 初始化函数,在类初始化时可以传入参数.第一个必须是self 实例本身.
	__init__(self[,var1,var2...]):
		# 通过方法绑定属性,动态绑定
		self.prop1=var1
		self.prop2=var2
		statement
	# 一般的方法,对比一般函数,第一个总是self 实例本身
	method1(self[,var1...]):
		print self.prop1

创建实例

创建实例就是类名(参数),参数取决于__init__方法.

# __init__(self)
obj=ClassName()
# __init__(self,var1,var2)
obj2=ClassName2(varA,varB)

访问限制

python没有真正的办法限制用户访问对象的属性/方法, 只能靠自觉了.以__开头的变量(__var__特殊变量除外) 不能直接用名字访问; 以_开头的变量暗示不要去访问,但不限制直接访问. 以__开头的变量其实可以用_className__var来访问.

class Student(object):
	__init__(self,name,score):
		# can't access directly
		self.__name=name
		# recommend not to access
		self._score=score
	get_name(self):
		return self.__name
	set_name(self,name):
		self.__name=name
s=Student("John",59);
s.__name="Mike"
# -> AttributeError: 'Student' object has no attribute '__name'
s._Student__name="Mike"
# OK!~

继承和多态

python的继承和多态比C++要简单太多..继承就是从父类继承一切, 多态就是重置一些父类也有的属性/方法,使其实现子类的特殊性.

继承的好处在于可以减少重用代码, 实现更抽象,也是多态的基础.

多态的好处在于有共同的某个方法,可以在传入后根据类的不同/特性来调用相应方法.

# 定义父类, 继承于新式类object
class Animal(object):
	def run(self): print "Animal is running"
# 定义子类, 继承于父类
class Dog(Animal):
	# 重载方法, 实现多态
	def run(self): print "Dog is running"
a=Animal()
d=Dog()
# isinstance 判断可以判断出其是否源于某个父类.
isinstance(d,Animal)
# True
isinstance(a,Dog)
# False

# 多态的好处在于有共同的某个方法,可以在传入后根据类的不同/特性来调用相应方法.
def runTwice(animal):
	animal.run()

Python还可以进行多重继承(指定多个父类), 通过多重继承来获得附属的新属性和功能, 这种设计又叫Mixin设计, 在C++/Java中均没有的功能.

多重继承时, 若多个父类中有相同的方法, 则排在前的父类将覆盖后面的,则越靠前越”主类”. 即使主类的方法源自父类的父类, 也依然优先.

# 定义主线父类, 继承于新式类object
class Animal(object):
	def eat(self): print "Animal can eat"
# 定义Mixin所用的"功能"类
class Flyable(object):
	def fly(self): print "Animal can fly"
class Runnable(object):
	def run(self): print "Animal can run"
# 进行多重继承
class Dog(Animal, Runnable): pass
class Cat(Animal, Runnable): pass
class Bird(Animal, Flyable): pass

新式类(object类)和传统类

Python2.1前,旧式类是唯一可用的类型, 在2.2中引入了新式类, 为了统一class和type的概念.

旧式类中的实例x, x.__class__对应的是其类,但type(x)永远都是 <type 'instance'>. 在新式类中, 一般情况下x.__class__type(x)都是统一的(因为私自可以改__class__).

旧式类的类型是<type 'classobj'>, 而新式类的类型则是<type 'type'>, 表面旧式类是源自于classobj,其实例源自于instance. 而新式类的则源于type, 并且其实例源自于对应的类. 引入新式类是为了使用元类来构造类对象, 统一类的模型. 一般新式类顶级的类是object,一般新式类均源于他. Python 3.x 全是新式类, 不需再继承object了.

新式类的使用有很多好处: 可以继承大部分内建类型, 引入了计算属性功能的descriptor(装饰器或者叫描述符, 如@property等), 使用各种特殊方法(如__str__,低级别的构造函数__new__,__slots__限定属性等), 元类的使用, 多重继承的一些问题.

class C():pass
class CC(object):pass
c=C();
cc=CC();
type(C)
# <type 'classobj'>
type(CC)
# <type 'type'>
type(c)
# <type 'instance'>
type(cc)
# <class '__main__.CC'>

print C
# __main__.C
print CC
# <class '__main__.CC'>
print c
# <__main__.C instance at 0x1096f4320>
print cc
# <__main__.CC object at 0x1096ed950>

# Python 2.7.10测试. 3.x测试结果可能不同.
dir(c)
# ['__doc__', '__module__']
dir(cc)
# ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

BB=CC
bb=BB();
print bb
# <__main__.CC object at 0x1096eda10>

以上是经典的查看经典类和新型类(继承自object)信息的代码. 经典类的类叫 classobj, 而新式类的类叫 type. 经典类对象的类是熟知的instance, 而新式类的对象的类则是创建该类的类对象__main__.CC. 打印出来的效果也是,新式类才是真的类,其对象也才是真的object对象.

新式类本事其实也是一个对象, 可以用变量接收, 可以作为函数参数传递甚至返回, 可以拷贝, 可以添加新属性, 可以创造对象(类的特性). 例如上述例子用BB接收类,用BB同样可以创造CC类的对象.

元类

元类就是类的类,用于创建各种类,一般类的元类是type类. 可以利用type方法来创建新式类(和class关键词效果相当).

细节请参考另一篇Python:元类metaclass.

类属性特殊处理

类的特殊属性/方法

请参考另一篇Python对象的特殊属性和方法.

属性

  • __slots__: 一个元组, 规定了可以设置的属性. 防止动态加载过多的属性.

方法

  • __new__: 构造函数, 创造类实例时的函数, 一般不修改.

类/对象的相关函数

  • type(obj): 获取对象的相应类型.
  • type(className, (parents), {attr:value}): 创建并返回一个类, 三个参数对于类名(字符串),父类(放在元组内)以及属性(属性/方法名以及对应值)
  • isinstance(obj, type): 判断对象是否和指定的type类型相等(type甚至可以是父类).
  • hasattr(obj, attr): 判断对象是否具有指定属性/方法
  • getattr(obj, attr[, default]): 获取属性/方法的值, 如设置default,要是没有该属性则返回缺失值(否则AttributeError). 类似于obj.attr
  • setattr(obj,attr,value): 设定该属性/方法的值. 类似于obj.attr=value
  • dir(obj): 获取相应对象的所有属性和方法名(字符串)的列表.

Reference

  1. Python对象的特殊属性和方法
  2. Python Datamodel, 中文版数据模型

本博文已合并到Python语法汇总中, 不再更新.



◆ 本文地址: http://platinhom.github.io/2015/10/20/pyObject/, 转载请注明 ◆

前一篇: Python:内建函数与对象方法
后一篇: Python中级篇


Contact: Hom / 已阅读()
Source 类别: Coding  标签: Python