1.1 对象 、值和类型
对象:专门用来存储数据的一块区域,对象中可以存放各种数据。
对象包含:编号id、类型type、值value 【要知道可变&不可变】
id:每个对象有唯一的id,由解析器生成,在Cpython,id就是对象的内存地址,不可变。'
type:用来标识当前对象所属的类型 type(),不可变。
value:对象中存储的具体数据,可变。Python中一共有number/string/tuple/dictionary/set/list六种基本数据类型。其中number/string/tuple是不可以修改的,dictionary/set/list是可以修改的。对象的可变性是根据其类型决定的。
1.2 类Class和实例Instance
(object)表示该类是从哪个类继承下来的
class Student(object):
pass
>>> bart = Student()
>>> bart
>>> Student
可以自由地给一个实例变量绑定属性,比如,给实例bart绑定一个name属性:
>>> bart.name = 'Bart Simpson'
>>> bart.name
'Bart Simpson'
通过定义一个特殊的__init__方法,在创建实例的时候,就把一些必要属性绑上去,类似于一个模板。(注意到__init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本)【__init__定义】
在类中可以定义变量和函数。注:和普通的函数相比,在类中定义的函数第一个参数永远是实例变量self,并且调用时不用传递该参数。
class Dog:
def __init__(self, name, age, gender, height):
self.name = name
self.age = age
self.gender = gender
self.height = height
def bark(self):
print('汪汪汪')
def bite(self):
print('%s嗷呜'%self.name)#把它想象成萝卜坑,后面括号里的变量就是萝卜,一个萝卜一个坑,一一对应填进去就是了
d= Dog('旺财', 8, 'male', 30) #
d.bite()
print(d.name,d.age,d.gender,d.height)
注:属性和方法查找流程:当前对象——>类
1.3 面向对象三大特征——封装、继承 、多态
封装(确保数据安全) 继承 (保证了对象的可扩展性)多态(保证了程序的灵活性)
【1】封装
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
从前面Student类的定义来看,外部代码还是可以自由地修改一个实例的name、score属性:
>>> bart = Student('Bart Simpson', 59)
>>> bart.score
59
>>> bart.score = 99
>>> bart.score
99
如果想要内部属性不被外部访问,可以把属性的名称前加上两个下划线__(在Python中,实例的变量名如果以__开头,就变成了一个私有变量)
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))
!!改完后,对于外部代码来说,没什么变动,但是已经无法从外部访问实例变量.__name和实例变量.__score了:
>>> bart = Student('Bart Simpson', 59)
>>> bart.__name #访问不了了
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'Student' object has no attribute '__name'
>>> bart._Student__name #这样是可访问的,私有变量并不是一定不能外部访问
'Bart Simpson'
>>> bart = Student('Bart Simpson', 59)
>>> bart.get_name()
'Bart Simpson'
>>> bart.__name = 'New Name' # 设置__name变量!错误的
>>> bart.__name
'New Name'
#此时只是给bart新增了一个__name变量,并没有改变原有的name
如果想要从外部获得name和score——给Student类增加get_name和get_score这样的方法。修改——增加set_score方法【知道怎么获取/修改私有变量】
class Student(object):
...
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__(双下划线开头结尾)是特殊变量,可直接访问
变量名类似_xxx (单下划线开头)“虽然可以访问,但最后不要随意访问”
变量名类似__xxx (双下划线开头)私有变量(可以通过_Student__name来访问__name变量:)
【2】继承
在定义类的时候,可以在类后的括号中指定当前类的父类、超类、基类
子类(衍生类)可以直接继承父类中的所有属性和方法,也可覆盖
class Animal:
def run(self):
print()
def sleep(self):
print()
class Dog(Animal):
def bark(self):
print('汪汪汪')
d = Dog()
d.bark()
d.run()
拓展:
supper() 可以用来获取当类的父类,并且通过supper()返回对象调用父类方法时,不需要传递self【好处是父类变了 ,不用改对应Animal.__init__(self,name)】
【3】多态
类似于Animal下面可以有Dog Cat......
1.4 实例属性和类属性
类属性——类的所有实例都可以访问到。
实例属性——各个实例所有,互不干扰;
不要对实例属性和类属性使用相同的名字,否则将产生难以发现的错误。
1.5 实例方法和类方法
实例方法:在类中定义,以self为第一个此参数的发方法
当通过实例调用时,会自动将当前调用对象作为self传入
当通过类调用时,不会自动传递self
a.test() 等价于 A.test(a)
类方法:在类内部使用@classmethod来修饰的方法属于类方法
类方法的第一个参数是cls,也会被自动传递,cls就是当前的类对象
@classmethod
def test(cls)
xxxx
你用class object调用f的时候,会发现MyClass.f的数据类型是function类,而用instance object调用f的时候,会发现x.f的数据类型却是method类
总体来讲,区分类/对象/属性
box.corner.x (去box引用的对象,并选择属性corner;接着去往那个对象,选择属性x)
class Rectangle:
"""
atteibutes: width, height, corner
"""
box = Rectangle()
box.width=100
box.height=200
box.corner=Point()
box.corner.x = 0
box.corner.y = 0