面向对象命名空间及组合(面试题)
命名空间 :
静态属性 : 属于类内部的命名空间
动态属性 : 属于类内部的命名空间
对象属性 : 属于对象的,在类内和self发生联系,在类外和对象名发生联系
可以查看静态属性的都有哪些:类名 对象名
可以调用类中的方法的有哪些:类名.方法名(对象),对象.方法名()
类到对象之间没有联系,而对象到类之间有联系。
对象在查找名的时候,会现在我自己的空间里找,再到类的空间里找
一、命名空间
属性:静态属性 (直接和类名关联或者直接定义在class下的变量)
对象属性 (在类内和self关联,在类外和对象名关联的变量)
动态属性(函数)
1、类的静态属性调用
在obj.name会先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常
其中类的数据属性是共享给所有对象的
class Foo: country = '中国' def __init__(self,name): self.name = name alex = Foo('alexander') # 实例化对象 egg = Foo('egon') print(Foo.country) # 中国 print(alex.country) # 中国 先找alex对象的内存,再找Foo的内存 print(egg.country) # 中国 alex.country = '印度' print(Foo.country) # 中国 print(alex.country) # 印度 print(egg.country) # 中国
2、给对象创建属性
创建一个对象/实例就会创建一个对象/实例的名称空间,存放对象/实例的名字,称为对象/实例的属性
class Foo: country = 'China' # 静态属性 类属性 country_lst = ['China'] def __init__(self,name): # 动态属性 self.name = name # 对象属性 alex = Foo('alexander') # 实例化对象 egg = Foo('egon') # 实例化对象 alex.age = 90 # 给对象创建一个age属性 print(alex.age) # 90
集合
class Foo: country = 'China' # 静态属性 类属性 country_lst = ['China'] def __init__(self,name): # 动态属性 self.name = name # 对象属性 alex = Foo('alexander') egg = Foo('egon') alex.age = 90 # 给对象创建一个age的属性
alex.country_lst = [] alex.country_lst.append('印度') print(alex.country_lst) # ['印度'] print(Foo.country_lst) # ['China'] Foo.role = 'Person' print(Foo.country) # China print(alex.name) # alexander print(egg.name) # egon alex.country = '印度' print(alex.country) # 印度 print(egg.country) # China print(Foo.country) # China del alex.country # 删除印度,重新指向 print(alex.country) # China print(alex.country_lst) # ['印度']
类名操作变量
不管操作可变还是不可变数据类型 都是类中对应的变量发生变化
对象名操作静态变量
引用变量:
先在自己的命名空间中查找,找不到就去类的命名空间找
修改变量:
如果是对可变数据类型中的元素进行修改,那么全局生效
如果是对变量进行重新赋值,那么只是在对象自己的命名空间里增加了一个新的属性
结论:应该尽量用类名去使用静态变量
对象名的使用顺序
class Person: def __init__(self):pass # 初始化 #给一个什么属性都没有的对象赋一些初识的属性 def eat(self): print('吃米饭') alex = Person() #裸着 print(alex.__dict__) alex.eat() # 吃米饭 alex.name = 'alexander' alex.eat = '喝粥' #对象使用名字的顺序:先用自己的,再用类的 # alex.eat() # 报错,括号里加字符串错误 #对象可以使用类的 #而类无法使用对象的 print(Person.eat) # <function Person.eat at 0x0000000001E88A60> print(alex.eat) #类对象指针的东西 alex = {'eat':eat} # 喝粥
二、面向对象组合
在一个类中以另一个类的对象做为数据属性,称为类的组合
例题、
例1:计算圆环的面积和周长
#圆形类 from math import pi class Circle: def __init__(self,r): self.radius = r def perimeter(self): return 2*pi*self.radius def area(self): return pi*(self.radius**2) #环形类 class Ring: def __init__(self,outer_r,inner_r): self.outer_circle = Circle(outer_r) self.inner_circle = Circle(inner_r) def perimeter(self): return self.outer_circle.perimeter()+self.inner_circle.perimeter() def area(self): return self.outer_circle.area() - self.inner_circle.area()
ring1 = Ring(20,10)
print(ring1.area()) # 面积
print(ring1.perimeter()) # 周长
# 既能hold住圆形的问题 # 又能解决环形的问题 函数方式
10,20 def func(arg1,arg2): outer_circle = Circle(20) inner_circle = Circle(10) print(outer_circle.area() - inner_circle.area()) def func2(arg1,arg2): outer_circle = Circle(20) inner_circle = Circle(10) print(outer_circle.perimeter() + inner_circle.perimeter()) # 500个环 ring1 = Ring(20,10) ring1.area()
例2、
老师有生日
class Teacher: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex # self.birth_year = year class Birthday: def __init__(self,year,month,day): self.year = year self.month = month self.day = day birthay1 = Birthday(1968,12,31) boss_gold = Teacher('lishi',40,'girl') boss_gold.birth = birthay1 print(boss_gold.birth.year) # 1968 print(boss_gold.birth.month) # 12 print(boss_gold.birth.day) # 31 print(boss_gold.name) # lishi print(boss_gold.sex) # girl
升级版
人,生日,课程
class Birthday: def __init__(self,year,month,day): self.year=year self.month=month self.day=day class Course: def __init__(self,name,price,teacher): self.name=name self.price=price self.teacher=teacher class Person: def __init__(self,name,birth,course): self.name=name self.birth=birth self.course=course B=Birthday(1999,12,24) C=Course('python',20000,'jing') haijiao=Person('haijiao',B,C) print(haijiao.name) #haijiao print(haijiao.birth.year) #1999 print(haijiao.birth.month) #12 print(haijiao.birth.day) #24 print(haijiao.course.name) #python print(haijiao.course.price) #20000 print(haijiao.course.teacher) #jing
3、人狗大战续集
#狗 class Dog: # 定义一个狗类 def __init__(self, name, breed, aggressivity, life_value): self.name = name # 每一只狗都有自己的昵称; self.breed = breed # 每一只狗都有自己的品种; self.aggressivity = aggressivity # 每一只狗都有自己的攻击力; self.life_value = life_value # 每一只狗都有自己的生命值; def bite(self,people): people.life_value -= self.aggressivity #人 class Person: # 定义一个人类 def __init__(self, name, aggressivity, life_value, money): self.name = name # 每一个角色都有自己的昵称; self.aggressivity = aggressivity # 每一个角色都有自己的攻击力; self.life_value = life_value # 每一个角色都有自己的生命值; self.money = money def attack(self,dog): dog.life_value -= self.aggressivity def get_weapon(self,weapon_obj): if self.money > weapon_obj.price: self.money -= weapon_obj.price # 金老板花钱买武器 self.weapon = weapon_obj # 金老板装备打狗棒 self.aggressivity += weapon_obj.aggr # 金老板的攻击力增加了 # boss_gold = Person('金老板',5,250,100) # huang = Dog('大黄','藏獒',100,3000) # huang.bite(boss_gold) # print(boss_gold.life_value) # boss_gold.attack(huang) # print(huang.life_value) #不公平 #武器装备 #人 有 武器 —— 组合 #武器:攻击力,名字,价格 class Weapon: def __init__(self,name,price,aggr): self.name = name self.price = price self.aggr = aggr dgb = Weapon('打狗棒',99.8,100) boss_gold = Person('金老板',5,250,100) huang = Dog('大黄','藏獒',100,3000) boss_gold.get_weapon(dgb) boss_gold.attack(huang) print(huang.life_value)
面试题
设计一个类,统计这个类被实例化的次数,且所有的对象共享这个属性
一、 class Foo: count = 0 def __init__(self): Foo.count += 1 f = Foo() print(f.count) # 1 f2 = Foo() print(f.count) # 2 f3 = Foo() print(f.count) # 3 二、 class Foo: count = 0 def __init__(self): Foo.count += 1 f = Foo() f2 = Foo() f3 = Foo() print(f.count) #Foo.count 3 print(f2.count) #Foo.count 3 print(f3.count) #Foo.count 3