一、army小练习
使用面向对象,实现army练习
创建一支军队:骑兵、法师、弓箭手
将军可以下达命令指挥军队
"""
创建一支军队:骑兵、法师、弓箭手
将军可以指挥军队下达命令
"""
class Cavalry:
def attack(self):
print("My iron rides on you!")
def defend(self):
print("cavalry defend!")
class Archer:
def attack(self):
print("My arrow is extremely accurate!")
def defend(self):
print("archer defend!")
class Magician:
def attack(self):
print("My magic is infinite!")
def defend(self):
print("magician defend!")
if __name__ == '__main__':
army = []
c = Cavalry()
m = Magician()
a = Archer()
army.append(c)
army.append(a)
army.append(m)
order = input("please order the army:")
if order == "attack":
for var in army:
var.attack()
elif order == "defend":
for var in army:
var.defend()
elif order == "flatten it":
for var in army:
if isinstance(var,Cavalry):
var.attack()
else:
var.defend()
elif order == "shoot it":
for var in army:
if isinstance(var,Archer):
var.attack()
else:
var.defend()
elif order == "magic it":
for var in army:
if isinstance(var,Magician):
var.attack()
else:
var.defend()
else:
print("The wind is too hard to hear the order!")
运行效果
please order the army:magic it
cavalry defend!
archer defend!
My magic is infinite!
二、@property
把一个方法当做属性来用
例如在方法前加上@property
会导致私有属性去私有化
使用@age.setter注意,三个age,必须是相同的
#把一个方法当做属性来用
class Person:
def __init__(self,n,age):
self.name = n
self.__age = age
@property
def age(self):
return self.__age
@age.setter #注意,三个age,必须是相同的
def age(self,n):
self.__age = n
if __name__ == '__main__':
p = Person("小红",18)
print(p.name)
#通过property可以像属性一样使用
p.age = 21
print(p.age) #导致私有属性去私有化
三、动态添加属性和方法
动态添加属性:类内没有的属性,可以直接添加
#动态添加属性
class Person:
pass
def tell(self):
print("my name is %s"%self.name)
if __name__ == '__main__':
p = Person()
#动态添加一个属性给当前实例,仅限于当前实例访问,其他实例不可以访问
p.name = "js"
print(p.name)
动态添加方法:
需要引用from types import MethodType
可以将一个类外的函数绑定给对象
tell是要绑定的函数,p是函数绑定到被指定的实例
p.speak = MethodType(tell,p)
#可以把一个方法动态的添加
from types import MethodType
#动态添加属性
class Person:
pass
def tell(self):
print("my name is %s"%self.name)
if __name__ == '__main__':
p = Person()
#动态添加一个属性给当前实例,仅限于当前实例访问,其他实例不可以访问
p.name = "js"
print(p.name)
#动态添加方法
#tell是要绑定的函数,p是函数绑定到被指定的实例
p.speak = MethodType(tell,p)
p.speak()
四、限制添加属性
在类内添加__slots__ = (“name”,)
可以现在添加属性,注意这里是元祖。
class Person:
#限制添加属性
__slots__ = ("name",) #注意这里是元祖,就算只有一个元素也必须要添加逗号
def __init__(self,name,age):
self.name = name
self.age = age
if __name__ == '__main__':
p = Person("js",11) #AttributeError: 'Person' object has no attribute 'age'
五、repr__和__str
当调用print打印实例的时候,才会调用str
而repr在文件交互模式下输入实例,按下回车的时候会自动调用
class Test:
def __init__(self,name = "jack",age = 19):
self.name = name
self.age = age
class TestStr(Test):
def __repr__(self):#当str不存在的时候,repr=str
return "__repr__: %s,%s"%(self.name,self.age)
def __str__(self):
return "__str__: %s,%s"%(self.name,self.age)
t = TestStr()
print(t.name)
print(t) #当调用print打印实例的时候,才会调用str
#而repr在文件交互模式下输入实例,按下回车的时候会自动调用
六、类方法和静态方法
它们都可以直接通过类名来调用
在写接口的时候,会使用这样的方法,这样就不用一直创建实例来调用le
class Person:
#类属性
name = "jeck"
def __init__(self,name):
self.name = name
def tell(self): #self 接收的是rose
print(self.name)
@classmethod
def say(cls): #cls接收类,打印类属性
print(cls.name)
@staticmethod
def talk(): #
print(Person.name)
if __name__ == '__main__':
p = Person("rose")
p.tell() #rose
p.say() #jeck
p.talk() #jeck
Person.tell(p) #rose 这种写法不实用
Person.say() #jeck
Person.talk() #jeck
练习
class Date:
def __init__(self,year = 0,month = 0,day = 0):
self.year = year
self.month = month
self.day = day
def show(self):
print(self.year,self.month,self.day)
@staticmethod
def get_date(string_date):
year, month, day = string_date.split("-")
date1 = Date(year,month,day) #这里必须为类名,如果类名变化,也需要变化
return date1
@classmethod
def get_dateL(cls,string_date):
year, month, day = string_date.split("-")
date1 = cls(year, month, day) #这里为cls而不是类名,可以随意修改类名
return date1
if __name__ == '__main__':
"""
假设用户输入2020-3-13
"""
t = Date.get_date("2020-3-13")
t.show()
t = Date.get_dateL("2020-3-13")
t.show()
注意:当需要对输入进行分割用split