1 类和实例
类的定义方式:class关键字
class Student(object):
pass
class后的Student表示类名,object表示所有类都会继承的类
下面根据类创建实例:类名+()实现
bart = Student()
print(bart)
print(Student)
<__main__.Student object at 0x000001791DA54C70>
<class '__main__.Student'>
bart指向Student的实例,at后为内存地址。
给实例bart绑定name属性
bart.name = 'Bart Simpson'
bart.name
'Bart Simpson'
通过定义一个特殊的__init__方法,在创建实例的时候,就把name,score等属性绑上去:
class Student(object):
def __init__(self,name,score):
self.name = name
self.score = score
self表示创建的实例本身。用init方法创建实例之后,不能传入空的参数,必须与init方法中的参数匹配
bart = Student('Bart Simpson',59)
print(bart.name)
print(bart.score)
Bart Simpson
59
在类中定义函数和普通函数的区别是:第一个参数永远是实例变量self且在调用时不用传递该参数。
1.1 数据封装
直接在Student类的内部定义访问数据的函数
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))
bart = Student('Bart Simpson',59)
bart.print_score()
Bart Simpson:59
2 访问限制
如果要让内部属性不被外部访问,可以在属性的名称前加上两个下划线__(变为私有属性/变量)
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))
bart = Student('Bart Simpson',59)
bart.__name
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-12-f1e304b30ef3> in <module>
7
8 bart = Student('Bart Simpson',59)
----> 9 bart.__name
AttributeError: 'Student' object has no attribute '__name'
外部代码需要获取name和score
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))
def get_name(self):
return self.__name
def get_score(self):
return self.__score
#修改分数
def set_score(self, score):
if 0 <= score <= 100:
self.__score = score
else:
raise ValueError('bad score')
变量名类似__ xxx __ 的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用 __ name __ 、__ score __ 这样的变量名。
3 继承和多态
定义一个class时,可以从现有class继承,新的class称为子类,被继承的class称为基类、父类或超类。
定义一个名为Animal的class,内部有run()方法可以直接进行打印。
class Animal(object):
def run(self):
print('Animal is running...')
编写Dog和Cat直接继承父类Animal的全部功能
class Dog(Animal):
pass
class Cat(Animal):
pass
dog = Dog()
dog.run()
cat = Cat()
cat.run()
Animal is running...
Animal is running...
当子类和父类存在相同方法的时候,子类的方法会覆盖父类的方法,在代码运行的时候总会调用子类的方法。这就是多态。
下面我们利用多态修改run()方法。
class Dog(Animal):
def run(self):
print("Dog is running")
class Cat(Animal):
def run(self):
print('Cat is running')
dog = Dog()
dog.run()
cat = Cat()
cat.run()
Dog is running
Cat is running
理解多态的好处:编写一个函数,函数接受一个Animal类型的变量
def run_twice(animal):
animal.run()
animal.run()
run_twice(Animal())
Animal is running...
Animal is running...
run_twice(Dog())
Dog is running
Dog is running
再定义一个Tortoise类型,从Animal派生:
class Tortoise(Animal):
def run(self):
print('Tortoise is running slowly...')
run_twice(Tortoise())
Tortoise is running slowly...
Tortoise is running slowly...
新增一个Animal的子类,不必对run_twice()做任何修改,实际上,任何依赖Animal作为参数的函数或者方法都可以不加修改地正常运行,原因就在于多态。
“开闭”原则:调用方只管调用,不管细节,而当我们新增一种Animal的子类时,只要确保run()方法编写正确,不用管原来的代码是如何调用的。
4 获取对象信息
4.1 使用type()判断对象类型
#基本类型的判断
print(type(123))
print(type('str'))
print(type(None))
#指向函数或者类的变量
print(type(abs))
<class 'int'>
<class 'str'>
<class 'NoneType'>
<class 'builtin_function_or_method'>
4.2 使用isinstance判断class类型
class Husky(object):
pass
#先创建3种类型的对象
a = Animal()
d = Dog()
h = Husky()
#进行判断
isinstance(h,Husky)
True
isinstance(h,Dog)
False
能用type()判断的基本类型也可以使用isinstance进行判断
print(isinstance('a',str))
print(isinstance(123,int))
print(isinstance(b'a',bytes))
True
True
True
判断变量是否为某些类型中的一种
isinstance([1,2,3],(list,tuple))
True
4.3 使用dir()获取一个对象的所有属性和方法。
#使用dir函数作用于对象,返回包含多个字符串的list
#获得一个字符串对象的所有属性和方法
dir('ABC')
['__add__',
'__class__',
'__contains__',
'__delattr__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__getitem__',
'__getnewargs__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__iter__',
'__le__',
'__len__',
'__lt__',
'__mod__',
'__mul__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__rmod__',
'__rmul__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'capitalize',
'casefold',
'center',
'count',
'encode',
'endswith',
'expandtabs',
'find',
'format',
'format_map',
'index',
'isalnum',
'isalpha',
'isascii',
'isdecimal',
'isdigit',
'isidentifier',
'islower',
'isnumeric',
'isprintable',
'isspace',
'istitle',
'isupper',
'join',
'ljust',
'lower',
'lstrip',
'maketrans',
'partition',
'replace',
'rfind',
'rindex',
'rjust',
'rpartition',
'rsplit',
'rstrip',
'split',
'splitlines',
'startswith',
'strip',
'swapcase',
'title',
'translate',
'upper',
'zfill']
仅仅列出class的属性和方法是不够的,配合getattr()、setattr()以及hasattr()可以直接操作对象的状态
class MyObject(object):
def __init__(self):
self.x=9
def power(self):
return self.x *self.x
obj = MyObject()
#测试对象属性
#判断属性x是否存在
print(hasattr(obj,'x'))
print(obj.x)
print(hasattr(obj,'y'))
#设置属性y
print(setattr(obj,'y',19))
print(getattr(obj,'y'))
obj.y
True
9
False
None
19
19
4.4 实例属性和类属性
Python是动态语言,根据类创建的实例可以任意绑定属性。
给实例绑定属性的方法通过实例变量或者通过self变量。
class Student(object):
def __init__(self,name):
self.name = name
s = Student('Bob')
s.score = 90
在class中直接定义的属性叫做类属性,归类所有,类的所有实例都可以访问到。
class Student(object):
name = 'Student'