# 人和狗的战争
class Dog:
def __init__(self, name, aggr, hp, kind): # 定义一条狗的属性
self.name = name # 初始化属性
self.aggr = aggr
self.hp = hp
self.kind = kind
def bite(self, person_obj): # 将人对象作为参数传入,即对于这个人,狗把他咬了,人减少的血量就是狗子的攻击力
person_obj.hp -= self.aggr # 作为外来参数做变化,person 不要 self. 操作
# 这个其实就是组合方法,即,一个对象的属性值是另一个类的对象
class Person:
def __init__(self, name, aggr, hp, sex): # 定义一个人的属性
self.name = name # 初始化属性
self.aggr = aggr
self.hp = hp
self.sex = sex
def attack(self, dog_obj): # 人有一个攻击的方法
dog_obj.hp -= self.aggr
two_ha = Dog('二哈', 25, 1000, '沙雕') # 生成一个"二哈"对象
ao_te_man = Person('迪迦', 30, 500, '不详') # 生成一个奥特曼对象
print('奥特曼的血量:', ao_te_man.hp) # 首先可以查看 奥特曼 的血量
print('二哈的血量:', two_ha.hp) # 首先可以查看 二哈 的血量
two_ha.bite(ao_te_man) # 二哈使用 bite 方法咬了奥特曼一口
ao_te_man.attack(two_ha) # 奥特曼使用 attack 方法攻击了 二哈
print('奥特曼剩余的血量:', ao_te_man.hp) # 首先可以查看 奥特曼 的血量
print('二哈剩余的血量:', two_ha.hp) # 首先可以查看 二哈 的血量
# 继承
class Animal:
def __init__(self, name, aggr, hp): # 初识化一个 Animal 类,具有以下属性
self.name = name
self.aggr = aggr
self.hp = hp
def eat(self): # 有一个 吃 的方法
self.hp += 100
print('加了100血量')
class Dog(Animal):
def __init__(self, name, aggr, hp, kind):
Animal.__init__(self, name, aggr, hp) # 继承父类的属性
# super().__init__(name, aggr, hp) # 一样的继承,不同的写法
self.kind = kind # 同时又有自己的属性,即派生属性
def eat(self):
Animal.eat(self) # 继承父类的方法
print('顺便做个练习1+1=', 1 + 1) # 继承过来可以做其他操作,这里引进一个 print 做示例
two_ha = Dog('狗子', 20, 100, '二哈')
print(two_ha.hp) # 先看一下二哈的血量
two_ha.eat() # 二哈调用继承父类的 eat 方法
print(two_ha.hp) # 再看一下二哈的血量
print(two_ha.__dict__) # 随便看看,调用 __dict__ 方法,以字典的形式查看当前对象的属性
super(Dog, two_ha).eat() # 直接使用被继承的父类方法
from abc import ABCMeta, abstractmethod # 第一步: 导入这个模块和方法,固定格式1
class Animal(metaclass=ABCMeta): # 第二步: 固定格式2
def __init__(self):
pass
@abstractmethod # 第三步: 固定格式3
def skill_1(self): pass # 并不实现
@abstractmethod
def skill_2(self): pass # 并不实现
class Dog(Animal): # 当父类使用了以上格式,只要是继承了父类,就要全部继承父类的方法
def skill_1(self): print('this is skill_1') # 重写方法
def skill_2(self): print('this is skill_2') # 重写方法
from abc import ABCMeta, abstractmethod
class Payment(metaclass=ABCMeta): # 定义一个支付类
def __init__(self):
pass
@abstractmethod
def pay(self):
pass
class WeChatPay(Payment): # 继承支付方法
def pay(self): print('微信支付')
class ALiPay(Payment): # 继承支付方法
def pay(self): print('支付宝支付')
class BankCardPay(Payment): # 继承支付方法
def pay(self): print('银行卡支付')
def all_pay(pay_obj): # 以上所有支付方式因为都有一个支付方法,所以写这一个方法
pay_obj.pay() # 所有支付对象调用同一个方法,就实现了统一支付入口
# 什么是多态
# python 动态强类型的语言
# 鸭子类型
# list tuple
# 不崇尚根据继承所得来的相似
# 我只是自己实现我自己的代码就可以了。
# 如果两个类刚好相似,并不产生父类的子类的兄弟关系,而是鸭子类型
# list tuple 这种相似,是自己写代码的时候约束的,而不是通过父类约束的
# 优点 : 松耦合 每个相似的类之间都没有影响
# 缺点 : 太随意了,只能靠自觉
class Person:
def __init__(self, name, password):
self.name = name
self.__password = password # 双下划线,即实现可私有属性
def __get_pwd(self): # 双下划线,即实现方法的私有
pwd = self.__password
return pwd
def return_pwd(self):
return self.__get_pwd()
# 所有的私有的属性或者方法都是在变量的左边加上双下划线
# 所有的私有属性和方法只能在类里面被使用,外部不能够直接调用类内部的私有属性或者方法
# 外部想要调用,则写一个方法get到类内部的属性或者方法
person = Person('张三', 123)
print(person.return_pwd())
# 会用到私有的这个概念de场景
# 1.隐藏起一个属性 不想让类的外部调用
# 2.我想保护这个属性,不想让属性随意被改变
# 3.我想保护这个属性,不被子类继承
from math import pi
class Circle:
def __init__(self, r):
self.r = r
@property
def perimeter(self):
return 2 * pi * self.r
@property
def area(self):
return self.r ** 2 * pi
c1 = Circle(5)
print(c1.area) # 圆的面积,在原本没有 @property 的时候,打印方式是 c1.area(),有了@property,去掉了(),伪装成了属性
print(c1.perimeter) # 圆的周长
class Person:
def __init__(self, name):
self.__name = name
@property
def obj_name(self): # 这里定义的函数名,在下面做修改或者删除时,最好用同一个函数名!!!装饰器的名字也一样,否则报错
return self.__name
@obj_name.setter # 伪装成属性,调用由 .obj_name() 变成 .obj_name
def obj_name(self, new_name):
self.__name = new_name
@obj_name.deleter
def obj_name(self):
del self.__name
person = Person('张三')
print(person.obj_name) # 结果是张三
person.obj_name = '李四' # 原本的使用方式是 person.obj_name(),这里直接使用属性方式修改
print(person.obj_name)
del person.obj_name # 执行删除操作
try:
print(person.obj_name)
except Exception as error:
print('名字属性不存在!', error)
class Goods:
__discount = 0.8 # 定义一个商品类,它的私有折扣属性是 0.8
@property
def get_discount(self):
return self.__discount
@classmethod # 使用 classmethod 装饰,即代表这个方法只是用来修改类的静态变量属性的,可被类名直接调用
def change_discount(cls, new_discount):
cls.__discount = new_discount
@staticmethod # 静态一般方法,只是放在了类里面
def func():
print('我只是一个放在类里面的一般函数')
good = Goods()
print(good.get_discount) # 此时折扣属性是 0.8
Goods.change_discount(0.9)
print(good.get_discount) # 此时折扣属性就是 0.9
Goods.func() # 可以被类名直接调用
good.func() # 也可以被类的对象调用
class A:
pass
class B(A):
pass
a_obj = A()
print(isinstance(a_obj, A)) # 判断 a_obj 是否是 A 的对象
print(issubclass(B, A)) # 判断 B 是否继承自 A
class Person:
kind = 'human'
def __init__(self, name, age):
self.name = name
self.age = age
@staticmethod
def func():
print('这是Person类里面的一个函数')
person = Person('张三', 25) # 定义一个人
# 放射对象属性
if hasattr(person, 'name'): # 如果有 'name' 属性 # 通过变量名的字符串形式取到的值
print(getattr(person, 'name')) # 就反射这个属性 # 一般 hasattr() 和 getattr() 配合起来用
# 反射对象的方法
if hasattr(person, 'func'):
getattr(person, 'func')() # getattr(person, 'func') 拿到一个内存地址,再加上 () 就执行该函数
# 反射类的属性
if hasattr(Person, 'kind'):
print(getattr(Person, 'kind'))
# 反射类的方法
if hasattr(Person, 'func'):
getattr(Person, 'func')()
# 反射内置模块方法
import time
if hasattr(time, 'asctime'):
print(getattr(time, 'asctime')())
# 如何反射本模块中的内容?★★★★★
import sys
man = 'happy'
# print(sys.modules[__name__]) # 代表本模块的地址,如果要反射本模块中的 man 属性,则
if hasattr(sys.modules[__name__], 'man'):
print(getattr(sys.modules[__name__], 'man'))
# 反射模块方法和类
from AAAAA import forload # AAAAA目录 里面有自己写 forload.py,内含一个类和方法
if hasattr(forload, 'func'): # 反射模块方法
getattr(forload, 'func')()
if hasattr(forload, 'BB'):
obj = getattr(forload, 'BB')() # 反射模块里面的类
obj.inner_func() # 反射成功,则 BB 类里面的方法被对象调用可以成功
class Teacher:
def __init__(self, name, salary):
self.name = name
self.salary = salary
def __str__(self):
return "Teacher's object"
teacher = Teacher('张三', 3000)
print(teacher) # 打印这个类的对象,实际上就是在调用 __str__ 方法,即实现高可定制
lis = [1, 2, 3]
# 还有很多,了解,后续基本不怎么用
###############################################################################
class A:
def __init__(self, name):
self.name = name
def __eq__(self, other): # 定制方法
if self.__dict__ == other.__dict__:
return True
else:
return False
ob1 = A('egon')
ob2 = A('egg')
print(ob1 == ob2) # 判断俩对象是否相等,== 本质是上执行的 __eq__
class Foo:
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
# 对象字典通过 key 取到 value
def __getitem__(self, item): # 将对象的属性按照字典的键值对形式,定制通过对象字典的 key 形式获取属性值
return self.__dict__[item]
def __setitem__(self, key, value): # 将对象的属性按照字典的形式,通过对象的 key 修改 value,即修改对象属性
self.__dict__[key] = value
def __delitem__(self, key): # 将对象的属性按照字典的形式,通过删除对象的 key 删除 value,即删除对象的默认属性
del self.__dict__[key]
person = Foo('张三', 25, '男')
print(person.name) # 原生方法支持的
print(person['name']) # 自己通过 __getitem__ 定制的,两者实现一样
person.name = '李四' # 原生方法支持的
print(person.name)
person['name'] = '王五' # 自己通过 __setitem__ 定制的,两者实现一样
print(person['name'])
# del person.name # 原生支持的删除属性的方法
# try:
# print(person.name)
# except Exception as error:
# print('找不到该属性', error)
del person['name'] # 自己通过 __delitem__ 定制的,两者实现一样
try:
print(person['name'])
except Exception as error:
print('找不到该属性', error)
class Person:
__instance = False # instance 为 True(非空),代表已经被示例化, 为 False (空),代表未被实例化
def __init__(self, name, age):
self.name = name
self.age = age
def __new__(cls, *args, **kwargs):
if cls.__instance: # 非空(已经被实例化),即返回原来的 cls.instance,实现单例了
return cls.__instance
cls.__instance = object.__new__(cls) # 未被实例化的话,就执行此操作
return cls.__instance
'''
object将__new__()方法定义为静态方法,并且至少需要传递一个参数cls,
cls表示需要实例化的类,此参数在实例化时由Python解释器自动提供。
'''
'''
1.调用__new__()方法来进行创建对象,这个new方法可以是object的,也可以是自己重写的,
最后必须要return这个创建好的对象的引用。
2.调用__init__()方法来进行实例对象的初始化,__init__(self)接收的就是new方法return出来的那个创建好的对象的引用。
返回对象的引用。
'''
'''
我们比较两个方法的参数,可以发现__new__方法是传入类(cls),
而__init__方法传入类的实例化对象(self),
而有意思的是,__new__方法返回的值就是一个实例化对象
ps:如果__new__方法返回None,则__init__方法不会被执行,
并且返回值只能调用父类中的__new__方法,而不能调用毫无关系的类的__new__方法。
我们可以这么理解它们之间的关系,__new__是开辟疆域的大将军,
而__init__是在这片疆域上辛勤劳作的小老百姓,只有__new__执行完后,开辟好疆域后,__init__才能工作。
'''
person_1 = Person('张三', 20)
print(person_1.__dict__)
print(id(person_1))
person_2 = Person('李四', 22)
print(person_2.__dict__)
print(id(person_2)) # 两个对象 id 是一样的
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。