OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
特性:封装,继承,多态
1.类
在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。
1)创建类:(实例模板)
名词--属性
动词--方法
Eg:
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)
lisa = Student('Lisa Simpson', 87)
bart.print_score()
lisa.print_score()
注意到__init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。
2)实例可以自由绑定属性/方法(类也可以)
#为实例绑定属性/方法,只对当前实例有效>>> bart.name = 'Bart Simpson' >>> bart.name 'Bart Simpson'---------------------------------->>> def set_age(self, age): # 定义一个函数作为实例方法
... self.age = age ... >>> from types import MethodType >>> s.set_age = MethodType(set_age, s) # 给实例绑定一个方法 >>> s.set_age(25) # 调用实例方法 >>> s.age # 测试结果 25#为了作用于所有实例可为类绑定
>>> def set_score(self, score): ... self.score = score ... >>> Student.set_score = set_scor
>>> s.set_score(100) >>> s.score 100 >>> s2.set_score(99) >>> s2.score 99#实例绑定可覆盖类同名属性
class Student(object):
name = 'Student'
#当我们定义了一个类属性后,这个属性虽然归类所有,但类的所有实例都可以访问到。来测试一下:
>>> 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
怎么限制呢?----类内__slot__变量
class Student(object):
__slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
然后,我们试试:
>>> s = Student() # 创建新的实例
>>> s.name = 'Michael' # 绑定属性'name'
>>> s.age = 25 # 绑定属性'age'
>>> s.score = 99 # 绑定属性'score'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'score'
(__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的。
子类实例允许定义的属性=自身的__slots__+父类的__slots__。)
3)数据封装
在类内自定义xxxset和xxxget方法,内部细节透明化
class Student(object):
...
def get_grade(self):
if self.score >= 90:
return 'A'
elif self.score >= 60:
return 'B'
else:
return 'C'
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
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute '__name'
外部想获取/修改----类内设置set和get
注意:
1.变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用__name__、__score__这样的变量名。
2.一个下划线开头的实例变量名,比如_name,约定俗成的规定意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”
3.事实上,__开头的变量也是可以在类外访问的,因为私有化实际上是python解释器对变量改名。访问方式_类名__私有变量(eg: _Student__name),强烈建议不要访问。
3.继承
从父类/基类/超类继承现有框架(变量,方法),发展新特性(自己的变量,方法)
子类获得了父类的全部功能,python允许多重继承。
Eg:
#比如,我们已经编写了一个名为Animal的class,有一个run()方法可以直接打印:
class Animal(object):
def run(self):
print('Animal is running...')
#当我们需要编写Dog和Cat类时,就可以直接从Animal类继承:
class Dog(Animal):
pass
class Cat(Animal):
pass
类型判断 isinstance和type
isinstance:子类=父类,父类!=子类
a = list() # a是list类型 b = Animal() # b是Animal类型 c = Dog() # c是Dog类型 >>> isinstance(a, list) True >>> isinstance(b, Animal) True >>> isinstance(c, Dog) True >>> isinstance(c, Animal) True #父类!=子类 >>> b = Animal() >>> isinstance(b, Dog) False#----------------------其他判断
>>> isinstance(d, Dog) and isinstance(d, Animal) True
>>> isinstance('a', str)
True
>>> isinstance(123, int)
True
>>> isinstance(b'a', bytes)
True
>>> isinstance([1, 2, 3], (list, tuple)) True >>> isinstance((1, 2, 3), (list, tuple)) True
type():返回对应的Class类型
#基本类型
>>> type(123)
<class 'int'>
>>> type('str')
<class 'str'>
>>> type(None)
<type(None) 'NoneType'>
#-------------------
#变量指向的类/函数
>>> type(abs)
<class 'builtin_function_or_method'>
>>> type(a)
<class '__main__.Animal'>
返回class类型
>>> 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
4.多态
子类使用同名方法覆盖父类方法
class Dog(Animal):
def run(self):
print('Dog is running...')
class Cat(Animal):
def run(self):
print('Cat is running...')-------------------------------------
Dog is running... Cat is running...
应用:接收父类参数,可接受传入子类
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...
来源:https://www.cnblogs.com/jpga/p/12581158.html