面向对象命名空间及组合

时间:2022-12-15 21:57:11

一、命名空间

属性:静态属性 (直接和类名关联或者直接定义在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,20def 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