目录
一、面向对象编程的概念Object Oriented Programming(OOP)
1、面向对象编程的含义:将对象视作程序的基本单元,一个对象包含了数据和操作数据的函数。每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。
2、面向过程编程的含义:将计算机程序视作一系列的命令集合,即一组函数的顺序执行。然后为简化程序设计,再将函数切分为子函数,即通过把大函数切割成小函数来降低系统复杂度。
3、二者差别:如果采用面向对象的程序设计思想,我们首选思考的不是程序的执行流程,而是Student
这种数据类型应该被视为一个对象,这个对象拥有name
和score
这两个属性(Property)。如果要打印一个学生的成绩,首先必须创建出这个学生对应的对象,然后,给对象发一个print_score
消息,让对象自己把自己的数据打印出来。给对象发消息实际上就是调用对象对应的关联函数,我们称之为对象的方法(Method)。
一个class既包含数据又包含针对数据的方法。
二、类和实例
1、类和实例的关系:类是抽象的模板,实例是根据类创建出的具体的对象,每个对象有相同的方法,但各自的数据可能各不相同。
2、类的定义:
- 一般用大写开头的名称定义类;
- (object)为所定义类要继承的类,如果没有合适的继承类就用object类,这是每个类都继承的类(老祖宗?)
class Student(object):
pass
3、实例的创建:
- 创建格式:实例名=类名()
>>> bart = Student()
>>> bart
<__main__.Student object at 0x10a67a590>
>>> Student
<class '__main__.Student'>
4、类的__init__方法:
- 是一个初始化,将该类所必须的属性强制填写进去
- 第一个参数是self,表示实例自身
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
- 和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量
self
5、访问限制
(1)对于类内部的参数,以两个下划线_ _开头命名则为私有变量,外部不能够访问;这样做的好处在于保证外部代码不能随意更改对象内部的状态
(2)要注意_ _***_ _是可以访问的,并不是私有变量,而仅开头有两个下划线则为私有变量
(3)当数据被封装为私有变量时,可以在类内部定义接口函数,让外部可以获取或者设定更改内部数据数值;此时该接口函数能够对输入数据进行筛选限制,避免传入无效参数,更加可控
(4)定义单下划线开头的变量时,其仍为公开变量,但是按照约定俗成尽量认作私有变量
(5)事实上,所谓的_ _***私有变量只不过是被更改了变量名,一般是给加上了前缀变成了“_类名_ _***”。这样的变量,实际上还是能够通过更改后的名字访问,但是由于不同python解释其对其更改可能不同,所以不该这样直接访问。
例子:下边的程序看似更改了私有变量,实际上只是在其内部重新定义了一个新的_ _name,并没有更改实际的内部变量_ _name
>>> bart = Student('Bart Simpson', 59)
>>> bart.get_name()
'Bart Simpson'
>>> bart.__name = 'New Name' # 设置__name变量!
>>> bart.__name
'New Name'
“总的来说就是,Python本身没有任何机制阻止你干坏事,一切全靠自觉”
三、继承和多态
1、继承:子类自动拥有父类(基类、超类)的全部方法
- 可以对父类的方法进行重定义覆盖
- 无论是抽象的子类与父类之间,还是实例与其抽象类之间,均存在类型从属关系,即:
b = Animal() # b是Animal类型的实例
class Dog(Animal):#Dog是Animal的子类
pass
c = Dog() # c是Dog类型的实例
>>> isinstance(b, Animal)#b是Animal类型
True
>>> isinstance(c, Dog)#c是Dog类型
True
>>> isinstance(c, Animal)# c也是Animal类型
True
>>> isinstance(Dog, Animal)# Dog也是Animal类型
True
- 判断是不是某个类型:isinstance() 返回布尔类型
3、多态:
不同的类中定义的相同名义的方法可以直接不加以区分地调用:以下例子中,def run(object)中的object名任给,在调用时只要object包含有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 running(something):#定义running
something.run()
print(isinstance(something,Animal))
class mytest(object):#定义一个非Animal子类的类包含running
def run(self):
print('I am running, too.')
running(Animal())
running(Dog())
running(Cat())
running(mytest())
#输出结果
Animal is running...
True
Dog is running...
True
Cat is running...
True
I am running, too.
False
4、关于静态语言与动态语言的差异:???【存疑】
静态语言就必须是同类下方可调用方式,但动态语言只需要保证有个相同的方式就行了,管你是这个类还是那个类?
四、获取对象信息
1、使用type()
- 通常可以用type(***)来判别其所属class类型
- 通过import types模块可以具体判断对象的函数类型
>>> 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
2、使用isinstance()
isinstance(A,objectB)
判断A是不是B的子类,返回为布尔类型
【一些使用方法】
- 也可以判别str int 等,类似于type
- 还能够判别对象是不是多种class中的一种
#isinstance()可以实现type()的功能:
>>> isinstance('a', str)
True
>>> isinstance(123, int)
True
>>> isinstance(b'a', bytes)
True
#还可以判别是不是多种class中的一种:
>>> isinstance([1, 2, 3], (list, tuple))
True
>>> isinstance((1, 2, 3), (list, tuple))
True
3、使用dir()
dir()作用:获得一个对象的所有属性和方法,返回一个list
>>> dir('ABC')
['__add__', '__class__',..., '__subclasshook__', 'capitalize', 'casefold',..., 'zfill']
#对len()函数的使用,其实其内部就是调用了目标对象的__len__方法
>>> len('ABC')
3
>>> 'ABC'.__len__()
3
对对象属性进行的操作:has、get、set
#对对象属性(attribute,attr)的判别分析
#hasattr(obj,'x'):有没有该属性?
#setsttr(obj,'x',***):设定一个属性
#getsttr(obj,'x',***):获取属性
>>> 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
#查找属性时,对于不存在的属性,可以给定返回值
>>> getattr(obj, 'z') # 获取属性'z'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'MyObject' object has no attribute 'z'
>>> getattr(obj, 'z', 404) # 获取属性'z',如果不存在,返回默认值404
404
- 可以通过del ***删除实例或类的属性:
>>> 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
>>> del Student.name
>>> print(Student.name)
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: type object 'Student' has no attribute 'name'
参考链接: