类 : 具备相同属性和技能的一类事物git
对象: 就是对一个类的具体的描述编程
实例化:类——>对象的过程函数
使用面向对象的好处:工具
结构上, 面向对象能够分为两部分:属性和方法ui
属性又叫静态属性、静态字段、静态变量编码
方法又叫动态属性、函数spa
class A: name = 'hello' #静态属性、静态字段、静态变量 def fun(self): #动态属性、方法、函数 pass
新建一个类,类名的首字母最好是大写的,规范一点,不然Pycharm有波浪号code
类的属性有两种方式查看orm
dir(类名):查出的是一个名字列表对象
类名.__dict__:查出的是一个字典,key为属性名,value为属性值
class Person: 静态变量 = 123 print(Person.__dict__) #内置的双下划线方法 执行输出: {'__doc__': None, '静态变量': 123, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__dict__': <attribute '__dict__' of 'Person' objects>} 从结果中,能够找到 '静态变量': 123
特殊的类属性
类名.__name__ # 类的名字(字符串) 类名.__doc__ # 类的文档字符串 类名.__base__ # 类的第一个父类(在讲继承时会讲) 类名.__bases__ # 类全部父类构成的元组(在讲继承时会讲) 类名.__dict__ # 类的字典属性 类名.__module__ # 类定义所在的模块 类名.__class__ # 实例对应的类(仅新式类中)
类名.__dict__['静态变量名'] 能够查看,可是不能删改 类名.静态变量名 直接就能够访问,能够删改 del 类名.静态变量名 删除一个静态变量
类名.方法名 查看这个方法的内存地址
类名.方法名(实参) 调用了这个方法,必须传一个实参,这个实参传给了self
class Person: 静态变量 = 123 #静态属性,静态变量 role = 'person' def f1(self): #默认带一个参数self,方法,动态属性 print(1234567) #引用动态变量 Person.f1() # 执行报错:TypeError: f1() missing 1 required positional argument: 'self' # 提示缺乏一个参数self 随便传一个参数,再次执行 Person.f1(1)
只要是类的方法,必需要传self。self的名字,是约定俗成
产生一个实例(对象)的过程:对象 = 类名()
实例化对象的过程有几步:
初始化方法,功能就是给对象self封装属性
class Person: role = 'person' #静态属性 def __init__(self,name,sex,hp,ad): self.name = name self.sex = sex self.hp = hp self.ad = ad summer = Person('summer','M',1,5) print(summer.__dict__)
广义上的属性,是指对象的属性
在类里面的def 通常叫方法。没有顺序之分,通常把init放到第一个.
class Person: role = 'person' #静态属性 def __init__(self,name,sex,hp,ad): self.name = name self.sex = sex self.hp = hp self.ad = ad def attack(self): print('{}发起了一次攻击'.format(self.name)) summer = Person('ss','M',1,5) # 执行类方法,下面2种方法效果等同 Person.attack(summer) # attack是和Person关联起来的,因此外部能够直接调用attack方法 summer.attack() ''' 执行输出: ss发起了一次攻击 ss发起了一次攻击 '''
方法的调用 :
1.类名.方法名(对象名) 方法中的self参数就指向这个对象
2.对象名.方法名() 这样写至关于方法中的self参数直接指向这个对象,推荐使用
① 查看类中全部的属性和方法:__dict__。虽然__dict__也能查看类中某一个属性,可是一般用来查看类中的全部属性和方法,不作其余用途
② 增删改查类中的属性:用万能的点(类中没有该属性就增,有该属性就改)
③ 操做类中的方法:通常不经过类名(通常经过对象名)
类名操做静态属性
(1)查看类中的全部内容:类名.__dict__方式
class Human: mind = '有思想' # 第一部分:静态属性 属性 静态变量 静态字段 dic = {} l1 = [] def work(self): # 第二部分:方法 函数 动态属性 print('人类会工做') print(Human.__dict__) print(Human.__dict__['mind']) Human.__dict__['mind'] = '无脑' # 报错
经过.__dict__这种方式只能查询,不能增删改.。第一种方式只用户查询所有内容(通常不用单独属性查询).
(2)经过万能的点 能够增删改查类中的单个属性
class Human: mind = '有思想' def work(self): # 第二部分:方法 函数 动态属性 print('人类会工做') Human.walk = '直立行走' # 增 del Human.mind # 删 Human.mind = '无脑' # 改 print(Human.mind) # 查
对以上两种作一个总结:
类名操做动态方法
除了两个特殊方法:静态方法,类方法以外,通常不会经过类名操做一个类中的方法。
class Human: mind = '有思想' # 第一部分:静态属性 属性 静态变量 静态字段 def work(self): # 第二部分:方法 函数 动态属性 print('人类会工做') def tools(self): print('人类会使用工具') Human.work(111) Human.tools(111) # 下面能够作,但不用。 Human.__dict__['work'](111)
实例化一个对象总共发生了三件事:
对象操做对象空间
(1)对象查询对象中全部属性 对象.__dict__
class Human: mind = '有思想' language = '实用语言' def __init__(self,name,sex,age,hobby): # self 和 obj 指向的是同一个内存地址同一个空间,下面就是经过self给这个对象空间封装四个属性。 self.n = name self.s = sex self.a = age self.h = hobby obj = Human('barry','男',18,'运动') print(obj.__dict__) # {'n': 'barry', 'h': '运动', 's': '男', 'a': 18}
(2)对象操做对象中的单个属性 万能的点 .
class Human: mind = '有思想' language = '实用语言' def __init__(self,name,sex,age,hobby): # self 和 obj 指向的是同一个内存地址同一个空间,下面就是经过self给这个对象空间封装四个属性。 self.n = name self.s = sex self.a = age self.h = hobby obj = Human('barry','男',18,'运动') obj.job = 'IT' # 增 del obj.n # 删 obj.s = '女' # 改 print(obj.s) # 查
(3)对象查看类中的属性
class Human: mind = '有思想' language = '实用语言' def __init__(self,name,sex,age,hobby): self.n = name self.s = sex self.a = age self.h = hobby obj = Human('barry','男',18,'运动') print(obj.mind) # 有思想 print(obj.language) # 实用语言
(4)对象操做类中的方法
class Human: mind = '有思想' language = '实用语言' def __init__(self,name,sex,age,hobby): self.n = name self.s = sex self.a = age self.h = hobby def work(self): print(self) print('人类会工做') def tools(self): print('人类会使用工具') obj = Human('barry','男',18,'运动') obj.work() obj.tools() ''' 执行输出: <__main__.Human object at 0x000001576C1808C8> 人类会工做 人类会使用工具 '''
一个类能够实例化多个对象
class Human: mind = '有思想' language = '实用语言' def __init__(self,name,sex,age,hobby): self.n = name self.s = sex self.a = age self.h = hobby def work(self): print(self) print('人类会工做') def tools(self): print('人类会使用工具') obj1= Human('李易峰','男',20,'拍戏') obj2= Human('赵丽颖','女',18,'唱歌') print(obj1,obj2) print(obj1.__dict__) print(obj2.__dict__) ''' 执行输出: <__main__.Human object at 0x00000223534C0D88> <__main__.Human object at 0x00000223534C68C8> {'n': '李易峰', 's': '男', 'a': 20, 'h': '拍戏'} {'n': '赵丽颖', 's': '女', 'a': 18, 'h': '唱歌'} '''
练习:在终端输出以下信息
小明,10岁,男,上山去砍柴
小明,10岁,男,开车去东北
小明,10岁,男,最爱大保健
老李,90岁,男,上山去砍柴
老李,90岁,男,开车去东北
老李,90岁,男,最爱大保健
老张…
class Person(object): def __init__(self, name, age, sex='男', hobby=('上山去砍柴', '开车去东北', '最爱大保健')): self.name = name self.age = age self.sex = sex self.hobby = hobby def info(self): for i in self.hobby: print('{},{}岁,{},{}'.format(self.name, self.age, self.sex, i)) ming = Person('小明', 10) li = Person('老李', 90) ming.info() li.info()
扩展题:使用面向对象的方式编码三级菜单
将以前的代码复制粘贴过来,切割成面向对象方式
# -*- coding: utf-8 -*- class AreaMenu(object): def __init__(self): self.zone = { '山东': { '青岛': ['四方', '黄岛', '崂山', '李沧', '城阳'], '济南': ['历城', '槐荫', '高新', '长青', '章丘'], '烟台': ['龙口', '莱山', '牟平', '蓬莱', '招远'] }, '江苏': { '苏州': ['沧浪', '相城', '平江', '吴中', '昆山'], '南京': ['白下', '秦淮', '浦口', '栖霞', '江宁'], '无锡': ['崇安', '南长', '北塘', '锡山', '江阴'] }, '浙江': { '杭州': ['西湖', '江干', '下城', '上城', '滨江'], '宁波': ['海曙', '江东', '江北', '镇海', '余姚'], '温州': ['鹿城', '龙湾', '乐清', '瑞安', '永嘉'] } } self.province = list(self.zone.keys()) self.run() def run(self): # 省列表 while True: print('省'.center(20, '*')) for i in self.province: # 打印省列表 print('{}\t{}'.format(self.province.index(i) + 1, i)) province_input = input('请输入省编号,或输入q/Q退出:').strip() if province_input.isdigit(): province_input = int(province_input) if 0 < province_input <= len(self.province): province_id = province_input - 1 # 省编号,因为显示加1,获取的时候,须要减1 city = list(self.zone[self.province[province_id]].keys()) # 城市列表 self.city(province_id, city) # 进入市区列表 else: print("\033[41;1m省编号 {} 不存在!\033[0m".format(province_input)) elif province_input.upper() == 'Q': break else: print("\033[41;1m输入省编号非法!\033[0m") def city(self, province_id, city): # 市区列表 if province_id == '' or city == '': return 'province_id 和 city 参数不能为空' while True: print('市'.center(20, '*')) for j in city: print('{}\t{}'.format(city.index(j) + 1, j)) city_input = input("请输入市编号,或输入b(back)返回上级菜单,或输入q(quit)退出:").strip() if city_input.isdigit(): city_input = int(city_input) if 0 < city_input <= len(city): city_id = city_input - 1 # 市编号,因为显示加1,获取的时候,须要减1 county = self.zone[self.province[province_id]][city[city_id]] # 县列表 self.county(county) # 进入县列表 else: print("\033[41;1m市编号 {} 不存在!\033[0m".format(city_input)) elif city_input.upper() == 'B': break elif city_input.upper() == 'Q': exit() # 因为在多层while循环里面,直接exit退出便可 else: print("\033[41;1m输入市编号非法!\033[0m") def county(self, county): # 县列表 if county == '': return 'county 参数不能为空' while True: print('县'.center(20, '*')) for k in county: print('{}\t{}'.format(county.index(k) + 1, k)) # 到县这一级,不能输入编号了,直接提示返回菜单或者退出 county_input = input("输入b(back)返回上级菜单,或输入q(quit)退出:").strip() if county_input == 'b': # 终止此层while循环,跳转到上一层While break elif county_input == 'q': # 结束程序 exit() else: print("\033[41;1m已经到底线了,请返回或者退出!\033[0m") if __name__ == '__main__': AreaMenu()
执行输出: