(一)实例方法
(1)__init__() 为构造方法(特殊的实例方法),第一个参数必须为 self 参数。
(2)self 代表该方法的调用者,即谁在调用该方法,那么 self 就代表谁。
(3)类里面的jump()和run()方法为实例方法。
(4)在使用 Python 编程时,一般不需要使用类方法或静态方法(不具体介绍)。
代码:
class Human: def __init__(self): print("在用构造方法") def jump(self): print("正在执行jump方法") def run(self): print("正在执行run方法") #使用self参数调用jump() self.jump() man = Human() man.jump() man.run()
结果:
在用构造方法 正在执行jump方法 正在执行run方法 正在执行jump方法
(二)类属性和实例属性
(1)类变量
类变量推荐直接用类名访问,但也可以使用对象名访问。
代码:
class Human: name = '泰戈尔' book = '飞鸟集' def info(self): #直接访问类变量会报错 #print(name)报错 #通过类名来访问类变量 print(Human.name) print(Human.book) #创建类对象 man = Human() man.info() #修改类变量 Human.name = '纳兰' Human.book = '人生若只如初见' man.info() #动态地为类和对象添加类变量 Human.age = '12' print(man.age)
结果:
泰戈尔 飞鸟集 纳兰 人生若只如初见 12
(2)实例变量
实例变量只能通过对象名访问,无法通过类名直接访问。
代码:
class Human: #定义两个变量 name = '泰戈尔' book = '飞鸟集' #定义实例方法 def change(self,name,book): #定义新的实例变量 self.name = name self.book = book #创建Human()对象 man = Human() print(Human.name) print(Human.book) man.change('纳兰','人生若只如初见') #访问man的name book实例变量 print(man.name)#纳兰 print(man.book)#人生若只如初见
结果:
泰戈尔 飞鸟集 纳兰 人生若只如初见
(三)定义属性:property()函数
(1)正常情况下的类,它包含的属性应该是隐藏的,只允许通过类提供的方法来间接实现对类属性的访问和操作。这种操作类属性的方式比较麻烦,更习惯使用“类对象.属性”这种方式。庆幸的是,Python 中提供了 property() 函数,可以实现在不破坏类封装原则的前提下,让开发者依旧使用“类对象.属性”的方式操作类中的属性。
(2)开发者调用 property() 函数时,可以传入 0 个(既不能读,也不能写的属性)、1 个(只读属性)、2 个(读写属性)、3 个(读写属性,也可删除)和 4 个(读写属性,也可删除,包含文档说明)参数。
代码:
class User: def __init__(self, first, last): self.first = first self.last = last def getfullname(self): return self.first + ',' + self.last def setfullname(self, fullname): first_last = fullname.rsplit(','); self.first = first_last[0] self.last = first_last[1] # 使用property()函数定义fullname属性,只传入2个参数 # 该属性是一个读写属性,但不能删除 fullname = property(getfullname, setfullname) u = User('孙', '悟空') # 访问fullname属性 print(u.fullname) # 对fullname属性赋值 u.fullname = '朱,八戒' print(u.first) print(u.last)
结果:
孙,悟空 朱 八戒
(四)python面向对象的三大特性
(1)封装
实际上封装有两个方面的含义:把该隐藏的隐藏起来,把该暴露的暴露出来。
python 小技巧:只要将 Python 类的成员命名为以双下画线“__”开头的,Python 就会把它们隐藏起来。
代码:
class User : def __hide(self): print('示范隐藏的hide方法') def getname(self): return self.__name def setname(self, name): if len(name) < 3 or len(name) > 8: raise ValueError('用户名长度必须在3~8之间') self.__name = name name = property(getname, setname) def setage(self, age): if age < 18 or age > 70: raise ValueError('用户名年龄必须在18在70之间') self.__age = age def getage(self): return self.__age age = property(getage, setage) # 创建User对象 u = User() u.name = '泰戈尔' u.age = 19 print(u.name) print(u.age)
结果:
泰戈尔 19
从该程序可以看出封装的好处,程序可以将 User 对象的实现细节隐藏起来,程序只能通过暴露出来的 setname()、setage() 方法来改变 User 对象的状态,而这两个方法可以添加自己的逻辑控制,这种控制对 User 的修改始终是安全的。
(2)继承
Python 中,实现继承的类称为子类,被继承的类称为父类(也可称为基类、超类)。
①多继承
代码:
class Fruit: def info(self): print("水果!重%g克" % self.weight) class Food: def taste(self): print("不同食物的口感不同") # 定义Apple类,继承了Fruit和Food类 class Apple(Fruit, Food): pass # 创建Apple对象 a = Apple() a.weight = 5.6 # 调用Apple对象的info()方法 a.info() # 调用Apple对象的taste()方法 a.taste()
结果:
水果!重5.6克 不同食物的口感不同
②父类方法重写
代码
class A: def foo(self): print("在父类中定义foo方法") class B(A): #重写父类的foo方法 def foo(self): print("子类重写父类中的foo方法") def bar(self): print("执行bar方法") #执行foo方法,将会调用子类重写之后的foo()方法 self.foo() A.foo(self) b = B() b.bar() a = A() print("---------------------") a.foo()
结果:
执行bar方法 子类重写父类中的foo方法 在父类中定义foo方法 --------------------- 在父类中定义foo方法