类和实例
class Student(object),object表示Student继承自object
init():构造方法,第一个参数必须为self
创建实例:Student(),self不用传入
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
def print_score(self):
print('%s: %s' % (self.name, self.score))
student = Student('A', 22)
student2 = Student('B', 23)
student.print_score()
student.age=18 //增加属性
print(student.age)
student2.aaa='aaa' //增加属性
print(student2.aaa)
访问限制
在class内部,定义变量为private ,以双下划线开头即为私有变量(不能以双下滑线结尾);
以双下滑线开头且以双下滑线结尾的变量,是特殊变量,可以直接访问该变量;
私有变量的本质:python解释器将变量名解释为_ClassName__privateName,用实例名也可以访问到,但是不同的python解释器,解释的变量名规则不一定是在变量名称前加入_ClassName
class T(object):
def __init__(self, name, age, expvar):
self.__name = name
self.__age = age
self.__expvar__ = expvar
def getName(self):
return self.__name
def setName(self, name):
self.__name = name
def getAge(self):
return self.__age
def setAge(self, age):
return self.__age
t = T('xm', 18, 'expvar')
print(t.getName()) --xm
t.__s = 18 //不会报错,只是新增了一个变量名为__name的变量,t.getName()还是原来的值
print(t.__s) --18
t.__name = 'zs'
print(t.getName()) --xm
print(t.__name) --zs
print(t.__age) --报错,私有变量无法访问
print(t.__expvar__) -- 输出 'expvar'
继承多态
定义类时,括号内的类就表示该类所继承的类,如:
class Animal(object) -- Animal类继承object类
class Dog(Animal) --Dog类继承Animal类
class Animal(object):
def run(self):
print('animal is running ...')
class Dog(Animal):
pass
class Cat(Animal):
pass
dog = Dog()
dog.run() --animal is running ...
cat = Cat()
cat.run() --animal is running ...
-----------重写run方法class Animal(object):
def run(self):
print('animal is running ...')
class Dog(Animal):
def run(self):
print('dog is running ...')
class Cat(Animal):
def run(self):
print('cat is running ...')
def run(animal):
animal.run()
run(Animal()) --animal is running ...
run(Dog()) --dog is running ...
run(Cat()) --cat is running ...
获取对象信息
- 基本类型信息
>>> type(123)==type(456)
True
>>> type(123)==int
True
>>> type('abc')==type('123')
True
>>> type('abc')==str
True
>>> type('abc')==type(123)
False
- 函数
>>> import types
>>> def fn():
... pass
...
>>> type(fn)==types.FunctionType
True
>>> type(abs)==types.BuiltinFunctionType
True
>>> type(lambda x: x)==types.LambdaType
True
>>> type((x for x in range(10)))==types.GeneratorType
True
- 类(class) 使用isinstance,能用type()判断的,也能用isinstance()判断
总是优先使用isinstance()来判断
>>> isinstance(dog, Dog)
True
>>> isinstance(dog, Animal) //继承
True
>>> isinstance([1, 2, 3], (list, tuple)) //类型是否是其中一种,满足至少一种即为True
True
>>> isinstance((1, 2, 3), (list, tuple))
True
获取对象的所有属性和方法,返回值是个list,操作对象属性
>>> dir('ABC')
['__add__', '__class__',..., '__subclasshook__', 'capitalize', 'casefold',..., 'zfill']
len(obj)自建函数,其实调用的是obj自身的__len__方法,如果想使用len(自定义类实例),在自定类中,加入__len__方法即可
仅仅把属性和方法列出来是不够的,配合getattr()、setattr()以及hasattr(),我们可以直接操作一个对象的状态
>>> hasattr(obj, 'x') # 有属性'x'吗?
True
>>> obj.x
9
>>> hasattr(obj, 'y') # 有属性'y'吗?
False
>>> setattr(obj, 'y', 19) # 设置一个属性'y'
>>> hasattr(obj, 'y') # 有属性'y'吗?
True
>>> getattr(obj, 'y') # 获取属性'y'
19
>>> obj.y # 获取属性'y'
19
如果试图获取不存在的属性,会抛出AttributeError的错误:
>>> getattr(obj, 'z') # 获取属性'z'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'MyObject' object has no attribute 'z'
可以传入一个default参数,如果属性不存在,就返回默认值:
>>> getattr(obj, 'z', 404) # 获取属性'z',如果不存在,返回默认值404
404
也可以获得对象的方法:
>>> hasattr(obj, 'power') # 有属性'power'吗?
True
>>> getattr(obj, 'power') # 获取属性'power'
<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
>>> fn = getattr(obj, 'power') # 获取属性'power'并赋值到变量fn
>>> fn # fn指向obj.power
<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
>>> fn() # 调用fn()与调用obj.power()是一样的
81
类属性和实例属性
从下面的例子可以看出,在编写程序的时候,千万不要对实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性。
>>> class Student(object):
... name = 'Student'
...
>>> s = Student() # 创建实例s
>>> print(s.name) # 打印name属性,因为实例并没有name属性,所以会继续查找class的name属性
Student
>>> print(Student.name) # 打印类的name属性
Student
>>> s.name = 'Michael' # 给实例绑定name属性
>>> print(s.name) # 由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性
Michael
>>> print(Student.name) # 但是类属性并未消失,用Student.name仍然可以访问
Student
>>> del s.name # 如果删除实例的name属性
>>> print(s.name) # 再次调用s.name,由于实例的name属性没有找到,类的name属性就显示出来了
Student