原创是:高淇老师讲义
Python 中 一切皆对象
=====================================================================================================================================
class Student:
school = "清华大学" # 类属性
count = 0 # 类属性
def __init__(self, name, score):# 构造方法(语言自带)
self.name = name # 实例属性
self.score = score
Student.count = Student.count+1
def say_score(self): # 实例方法(自定义)
print("学校是:", Student.school)
print(self.name, '的分数是:', self.score)
s1 = Student('张三', 80) # s1 是实例对象,自动调用__init__()方法
s1.say_score() # 实例对象调用实例方法
Student.say_score(s1)
print('一共创建{0}个 Student 对象'.format(Student.count))
=====================================================================================================================================
类-->类对象
类的实例-->实例对象
定义类
1、类名称 首字母大写,包含字母、数字、下划线,多个单词:驼峰命名
2、类成员 属性+方法
2.1、类属性
2.2、类方法
2.3、实例属性
2.4、实例方法
2.6、静态方法
2.7、语法定义的方法
实例对象,自动调用__init__(self[,])方法。
Python 对象包含三个部分:
1、id(identity 识别码)
2、type(对象类型)
3、value(对象的值)
属性(attribute)
方法(method)
=====================================================================================================================================
构造方法:
1、__init__(self[,])
2、构造方法作用:用来初始化实例对象的实例属性
3、构造函数调用 类名(参数)
4、__init__(self[,])方法 自己定义系统就不自动定义了,如果自己不定义,系统将自动定义一个不带参数的。
__new__()方法: 用于创建对象,无需重定义该方法,系统自动完成。
实例属性:实例对象的属性
1、实例属性一般在__init__()方法中
2、本类中访问:self.实例属性名
3、创建实例对象后访问:实例对象.实例属性名
4、实例对象可以自行添加实例属性(事先在类中并未定义改实例属性)
=====================================================================================================================================
实例方法:
1、def 方法名(self [, 形参列表]):
函数体
2、对象.方法名([实参列表])
3、特别需注意:实例方法第一个不管是否有自定义参数,参数列表第一个参数必须是self。实例对象调用实例方法时忽略self。
函数 vs 实例方法
1、特定功能的代码块
2、函数要用直接调用,实例方法则需要通过实例对象才能调用(类外部)
3、self
1、dir(obj)可以获得对象的所有属性、方法
2、obj.__dict__ 对象的属性字典
3、pass 空语句
4、isinstance(对象,类型)判断"对象"是不是"指定类型"
=====================================================================================================================================
类对象、类属性、类方法、静态方法
类属性:
类属性属于类对象,可以被所有实例对象共享。
=====================================================================================================================================
类方法:
类方法"类对象"的方法。
类方法通过装饰器@classmethod 来定义。
@classmethod
def 类方法名(cls[,形参列表]):
函数体
1、@classmethod 必须位于方法上面一行
2、cls
3、类方法调用:类名.类方法名
4、类方法访问实例属性和实例方法会导致错误。(原因:实例属性,实例方法是实例对象调用的,如果在类方法中直接调用,可能根本没实例对象)
5、...
pass 占位符
class Student:
school = "清华大学" # 类属性
@classmethod
def printCompany(cls):
print(cls.school)
Student.printCompany()
=====================================================================================================================================
静态方法:
@staticmethod
def 静态方法名([形参列表]) :
函数体
1、@staticmethod 必须位于方法上面一行
2、调用静态方法格式:"类名.静态方法名(参数列表)"
3、静态方法中访问实例属性和实例方法会导致错误
class Student:
@staticmethod
def add(a, b): # 静态方法
print("{0}+{1}={2}".format(a, b, (a+b)))
return a+b
Student.add(20, 30)
=====================================================================================================================================
__del__方法(析构函数)和垃圾回收机制
对象没有被引用时(引用计数为 0),由垃圾回收器调用__del__()方法。
系统会自动提供__del__方法,一般不需要自定义析构方法。
class Person:
def __del__(self):
print("销毁对象:{0}".format(self))
p1 = Person()
p2 = Person()
del p2
print("程序结束")
=====================================================================================================================================
__call__方法和可调用对象
class SalaryAccount:
def __call__(self, salary):
yearSalary = salary*12
return dict(yearSalary=yearSalary)
s = SalaryAccount()
print(s(150000))
=====================================================================================================================================
Python 中方法没有重载
方法签名包含 3个部分:
1、方法名
2、参数数量
3、参数类型
定义多个同名方法,只有最后一个有效。(最后一个覆盖了前面的)
=====================================================================================================================================
方法的动态性
class Person:
def work(self):
print("努力上班!")
def play_game(self):
print("{0}玩游戏".format(self))
def work2(s):
print("好好工作,努力上班!")
Person.play = play_game
Person.work = work2
p = Person()
p.play()
p.work()
Person.play 这个地方的play 在类中并未定义
Person.work 虽然定义了,还是可以重新赋值
通过右边的内容,确定左边的对象。
=====================================================================================================================================
私有属性和私有方法(实现封装)
1、两个下划线开头的属性是私有的。
2、类内部可以访问私有属性(方法)
3、类外部不能直接访问私有属性(方法)
4、类外部可以通过"_类名__私有属性(方法)"访问
class Employee:
__company = "xxx" # 私有类属性. 通过 dir 可以查到 _Employee__company
def __init__(self, name, age):
self.name = name
self.__age = age # 私有实例属性
def say_company(self):
print("我的公司是:", Employee.__company) # 类内部可以直接访问私有属性
print(self.name, "的年龄是:", self.__age)
self.__work()
def __work(self): # 私有实例方法 通过 dir 可以查到 _Employee__work
print("工作!好好工作,好好赚钱,娶个媳妇!")
p1 = Employee("110", 32)
print(p1.name)
print(dir(p1))
p1.say_company()
print(p1._Employee__age)
# 通过这种方式可以直接访问到私有属性。通过 dir 可以查到属性:_Employee__age
# print(p1.__age) #直接访问私有属性,报错
# p1.__sleep() #直接访问私有方法,报错
有属性"__age"在实际存储时是按照"_Person__age"这个属性来存储的。
=====================================================================================================================================
@property 装饰器
@property 可以将一个方法的调用方式变成"属性调用"
class Employee:
def __init__(self, name, salary):
self.name = name
self.__salary = salary
@property # 相当于 salary 属性的 getter 方法
def salary(self):
print("月薪为{0},年薪为{1}".format(self.__salary, (12*self.__salary)))
return self.__salary
@salary.setter
def salary(self, salary): # 相当于 salary 属性的 setter 方法
if(0 < salary < 1000000):
self.__salary = salary
else:
print("薪水录入错误!只能在 0-1000000 之间")
emp1 = Employee("高淇", 100)
print(emp1.salary)
emp1.salary = -200
=====================================================================================================================================
属性和方法命名总结
1、_xxx:保护成员,不能用“from module import * ”导入,只有类对象和子类对象能访问这些成员。
2、__xxx__:系统定义的特殊成员
3、__xxx: 类中的私有成员,只有类对象自己能访问,子类对象也不能访问。(但,在类外部可以通过“对象名. _类名__xxx”这种特殊方式访问。Python 不存在严格意义的私有成员)
注:再次强调,方法和属性都遵循上面的规则。