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