day15 面向对象(内置方法,魔术方法) 类属性 实例属性

作业讲解

"""
1.定义一个汽车类Vehicle,

		要求:	1.属性包括:汽车品牌brand、颜色color和速度speed, 其中速度的起始值是0。

				2.为属性提供访问的方法。注意:汽车品牌一旦初始化之后不能修改。

				3.方法有加速、减速。
"""
class Vehicle(object):
 def __init__(self,brand,color):
     #私有化
     self.__brand = brand
     self.color = color
     #速度的起始值是0
     self.speed = 0

 def add_speed(self,speed):
     self.speed += speed
     print("当前的车速为:%d" % (self.speed))

 def cut_speed(self,speed):
     if speed > self.speed:
         #print("抱歉,无法完成减速")
         self.speed = 0
     else:
         self.speed -= speed
         print("当前的车速为:%d" % (self.speed))

 #之提供获取的方法,不提供修改的方法
 # def get_brand(self):
 #     return self.__brand

 @property
 def brand(self):
     return self.__brand

v = Vehicle("兰博基尼","紫色")
v.add_speed(49)
v.cut_speed(20)

#print(v.get_brand())
print(v.brand)
"""
3.宠物店类 PetShop

			属性:店名,店中的宠物 【使用列表存储宠物】

			方法:展示所有宠物的信息
宠物狗类 PetDog

				属性:昵称,性别,年龄,品种

				方法:叫,拆家,吃饭
宠物猫类 PetCat

			属性:昵称,性别,年龄,品种,眼睛的颜色

			方法:叫,撒娇,吃饭
注意:狗的叫声是汪汪 猫的叫声是喵喵 狗吃的是⻣头 猫吃的是⻥
"""
#父类
class Pet(object):
 #公共的属性
 def __init__(self,name,gender,age,kind):
     self.name = name
     self.age = age
     self.gender = gender
     self.kind = kind

 #公共的方法
 def cry(self):
     print("crying")
 def eat(self):
     print("eating")

 def myprint(self):
     print(self.name,self.gender,self.age,self.kind)

#子类
class PetDog(Pet):
 #特有的方法
 def des_home(self):
     print(self.name + "拆家")

 #重写父类中的函数
 def cry(self):
     print("汪汪")
 def eat(self):
     print(self.name + "eating骨头")


class PetCat(Pet):
 def __init__(self, name, gender, age, kind,eye_color):
     super().__init__(name,gender,age,kind)
     self.eye_color = eye_color

 # 特有的方法
 def play(self):
     print(self.name + "撒娇")

 # 重写父类中的函数
 def cry(self):
     print("喵喵")

 def eat(self):
     print(self.name + "eating鱼")

 def myprint(self):
     print(self.name,self.gender,self.age,self.kind,self.eye_color)

class PetShop(object):
 def __init__(self,name,pet_list):
     self.name = name
     self.pet_list = pet_list

 def show(self):
     if self.pet_list:
         for pet in self.pet_list:
             #print(pet)
             pet.myprint()

             #多态,根据类型自动匹配调用哪个函数
             pet.eat()
             pet.cry()

             #调用子类特有的函数,直接调用会报错
             if isinstance(pet,PetDog):
                 pet.des_home()
             elif isinstance(pet,PetCat):
                 pet.play()
     else:
         print("还没有宠物,无法展示")

p1 = PetCat("aaa",0,3,"英短","棕色")
p2 = PetCat("bbb",0,3,"英短","棕色")
p3 = PetCat("ccc",0,3,"英短","棕色")

p4 = PetDog("aaa",0,3,"二哈")
p5 = PetDog("aaa",0,3,"泰迪")
p6 = PetDog("aaa",0,3,"二哈")

ps = PetShop("阳阳阳宠物店",[p1,p2,p3,p4,p5,p6])
ps.show()

一、面向对象

1.对象的内置函数
import types
#1.type():获取一个对象的类型,返回的结果:<class "类型">
print(type(10))
print(type("aaa"))
print(type(True))

#注意1:type可以进行比较==
print(type(10) == int)

#注意2:type()返回值的类型为type类型
print(type(type(10)))   #<class 'type'>

#注意3:判断一个对象是否是函数,使用types模块
print(type(lambda x:x) == types.LambdaType)
print(type((x for x in range(5))) == types.GeneratorType)
print(type(abs) == types.BuiltinFunctionType)

#2.isinstance():判断一个对象是否是指定的数据类型
print(type(10) == int)
print(isinstance(10,int))

#注意:可以判断一个对象是否是某些类型中的一种,只要符合一种,则返回True
print(isinstance([1,2,3],(list,tuple,dict)))
print(isinstance((1,2,3),(list,tuple,dict)))
print(isinstance("123",(list,tuple,dict)))

#3.dir(),获取一个对象的所有属性和方法,返回一个列表               *******
print(dir("fahf"))
print(dir([3,5]))


#4.issubclass(子类,父类):用来判断两个类之间的继承关系
class Person(object):
 pass
class Student(Person):
 pass

class Dog(object):
 pass

print(issubclass(Student,Person))  #True
print(issubclass(Person,Student))  #False
print(issubclass(Person,Dog))  #False
2.魔术方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ouxriQcw-1586254871686)(1.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bwL8F5ox-1586254871686)(2.png)]

#1.__str__和__repr__:返回对象的字符串描述信息,默认返回的是对象的地址

#a.
class Person(object):
 def __init__(self,name,age,hobby):
     self.name = name
     self.age = age
     self.hobby = hobby

p1 = Person("张三",10,"吹牛逼")
print(p1)   #<__main__.Person object at 0x1026bb160>
print(p1.__str__())  #<__main__.Person object at 0x1026bb160>

#b
class Person(object):
 def __init__(self,name,age,hobby):
     self.name = name
     self.age = age
     self.hobby = hobby

 #注意1:如果输出对象的时候不需要地址,需要对象的信息,则可以在类中重写__str__
 def __str__(self):
     #print("hello")  #TypeError: __str__ returned non-string (type NoneType)
     #注意2:__str__必须设置返回值,而且必须返回一个字符串,该字符串一般和对象的属性相关
     return  "%s-%d-%s" % (self.name,self.age,self.hobby)


p1 = Person("张三",10,"吹牛逼")
print(p1)
#print(p1.__str__())

print('=' * 30)

#c。
"""
repr和str的功能类似,都是用来修改一个对象的默认打印内容,在打印一个对象时,
如果在类中没有重写str,他会自动查找repr,如果这两个方法都没有,则直接打印该对象的地址

常用__str__
"""
class Person(object):
 def __init__(self,name,age,hobby):
     self.name = name
     self.age = age
     self.hobby = hobby

 def __str__(self):
     return  "%s-%d-%s" % (self.name,self.age,self.hobby)

 # def __repr__(self):
 #     return  "%s-%d-%s" % (self.name,self.age,self.hobby)
 #__repr__ = __str__    #函数是一个变量


p1 = Person("张三",10,"吹牛逼")
print(p1)
#2.__add__:但凡涉及到+号的运算,都是调用了该函数
#a
print(2 + 6)
print("abc" + "123")
print([2,3,4] + [4,5,6])
print((2,3,4) + (4,5,6))

#print("abc" + 6) #TypeError: can only concatenate str (not "int") to str
#print(6 + "abc") #TypeError: unsupported operand type(s) for +: 'int' and 'str'

#注意:对于不同的类型,+有不同的解释,所以支持+运算的数据类型,系统提供了__add__函数
# print(dir("abc"))
# print("abc".__add__("123"))
# print(dir([1,2,3]))
# print([1,2,3].__add__([4,5,6]))
# print(dir(10))

#b
class Person(object):
 def __init__(self,age,name):
     self.age = age
     self.name = name

 def __add__(self, other):
     #参与求和的对象:self和other
     #Person(self.age + other.age)表示创建对象,会调用init,注意参数的匹配
     return Person(self.age + other.age,self.name)

 def __str__(self):
     return "%s-%d" % (self.name,self.age)

 def show(self):
     print("show")

p1 = Person(18,"张三")
p2 = Person(8,"aaa")
#Person + Person = int ---->Person + Person = Person
print(p1 + p2) #TypeError: unsupported operand type(s) for +: 'Person' and 'Person'
print(p1.__add__(p2))
print(p1)

#工作原理
print((p1.__add__(p2).__str__()))

p3 = Person(10,"bbb")
print(p1 + p2 + p3)  #p1 + p2返回Person,然后再和p3相加

"""
p1.__add__(p2)---->temp:Person(26)
temp.__add__(p3) --->sub:Person(36)
sub.__str__()
"""

p1.show()

print(p1.name,p1.age)
#问题补充说明:__str__\__repr__\__add__

#1.
class Person(object):
 def __init__(self,name,height):
     self.name = name
     self.height = height

 def __str__(self):
     #注意1:只需要返回一个字符串,字符串的格式由需求而定,拼接几个属性由需求而定
     return "姓名:%s,身高:%.2f" % (self.name,self.height)

 # def __repr__(self):
 #     return "姓名:%s,身高:%.2f" % (self.name,self.height)
 __repr__ = __str__

p1 = Person("jack",175.0)
p2 = Person("李四",185.5)
#注意2:一般情况下,魔术方法都不需要手动调用,根据具体的使用场景会自动调用
print(p1)
print(p2)
#工作原理:p1.__str__()   p2.__str__()

list1 = [p1,p2]
for per in list1:
 print(per)

print(list1)

#2
class Student(object):
 def __init__(self,name,age,score):
     self.name = name
     self.age = age
     self.score = score

 def __add__(self, other):
     #注意:根据需求,自定义相加的内容【同种类型】
     return Student("aaa",5,self.score + other.score)

 def __str__(self):
     return str(self.score)

stu1 = Student("小花",10,100)
stu2 = Student("小王",9,66)

#需求:实现两个学生对象的相加,结果为成绩之和
print(stu1 + stu2)
#stu1.__add__(stu2)
print(type(stu1 + stu2))

print(stu1)
print(stu2)
#3.比较运算符
"""
>:__gt__  , greater than
<:__lt__  ,less than
>=:__ge__ ,greater equal
<=:__le__ ,less equal
==:__eq__ ,equal
!=:__ne__ ,not equal
"""
class Student(object):
 def __init__(self,name,age,score):
     self.name = name
     self.age = age
     self.score = score

 #重新实现系统函数,自定义比较的规则
 def __gt__(self, other):
     #参与比较的对象:self和other
     if self.score > other.score:
         return True
     elif self.score < other.score:
         return False
     else:
         return "相等"

stu1 = Student("小花",10,50)
stu2 = Student("小王",9,66)

#需求:比较两个学生的成绩高低
print(stu1 > stu2)    #True
print(stu1.__gt__(stu2))
3.类属性和实例属性【面试题】

类属性:类的字段 实例属性/对象属性:对象的字段

实例属性和类属性的区别:

​ a.定义的位置不同,类属性是直接定义在类中的属性,对象属性是定义在构造函数中的属性

​ b.对象属性使用对象访问,类属性使用类名访问

​ c.在内存中出现的时机不同【类属性随着类的加载而出现,对象属性随着对象的创建而出现】

​ d.优先级不同,对象属性的优先级高于类属性

​ e.使用场景不同:如果是对象特有的数据,则定义为对象属性,如果是多个对象共有的数据,则定义为类属性

class NZ2002(object):
 #1.定义位置不同
 #类属性:定义在类中
 num = 10
 name = "abc"

 teacher = "Disen老师"

 def __init__(self,name):
     #对象属性/实例属性:定义在构造函数中
     self.name = name

#2.在内存中出现的时机不同,类属性优先于对象属性出现在内存中
print(NZ2002.num)   #10
#print(NZ2002.name) #AttributeError: type object 'NZ2002' has no attribute 'name'

#3.调用方式不同
#类属性: 类名.类属性   或者  对象.类属性
print(NZ2002.num)
n = NZ2002("王猛")
print(n.num)

#对象属性:  对象.对象属性
print(n.name)

#4.优先级不同:当类属性和对象属性重名时,使用对象访问的时候对象属性的优先级高
print(n.name)

del n.name
print(n.name)

#5.使用场景不同:如果是对象特有的数据,则定义为对象属性,如果是多个对象共有的数据,则定义为类属性
dingxing = NZ2002("定兴")
daineng = NZ2002("代能")
dingxing.name = "吴帅哥"
print(dingxing.name)
print(daineng.name)

print(dingxing.teacher)
print(daineng.teacher)
4.类方法和静态方法

类方法:在方法前面有 @classmethod 装饰器的方法叫做类方法,类方法可以通过类名调用,也可以通过对象名调用,但是一般都通过类名调用

类方法必须有一个参数,这个参数我们一般写为 cls , cls代表就是当前类
​ a.类方法是属于整个类的,不是属于某个对象的,所以在类方法中禁止出现self
​ b.在类方法中,可以直接通过cls调用这个类的类属性和类方法
​ c.在类方法中,可以直接通过cls来创建对象,并且封装一层,最终通过类方法给外部提供简介的接口

静态方法:在方法前面有 @staticmethod 装饰器 的方法叫做静态方法,静态方法可以通过类名调用,也可以通过对象名调用,但是一般都通过类名调用

class Person(object):
 #构造方法
 def __init__(self,name):
     self.name = name

 #实例方法
 #特点:参数列表的第一个参数是self,self表示当前实例【对象】
 def show(self):
     print("showing",self)

 def check(self):
     print("check")
     self.show()

 #类方法
 #特点:参数列表的第一个参数是cls,cls代表当前类
 #注意:在类方法中调用实例方法,则可以通过cls先创建一个对象,然后调用
 @classmethod
 def func1(cls):
     print("类方法~~~~func1",cls)
     # 可以通过cls创建对象
     c = cls("jack")
     #对象.实例方法
     c.show()

 #静态方法
 #说明:形参没有特殊之处
 @staticmethod
 def func2():
     print("func2222222")


per = Person("张三")

#实例方法:对象.函数(实参列表),self不需要传参
per.show()
#Person.show(per)

#类方法:对象.函数(实参列表)  或者  类名.函数(实参列表)
per.func1()
Person.func1()

#静态方法:对象.函数(实参列表)  或者  类名.函数(实参列表)
per.func2()
Person.func2()

"""
总结:
 a.类方法一般和类属性配合使用
 b.如果封装工具类,类中的函数可以定义为类方法或者静态方法,直接使用类名调用
 c.如果在函数内部需要创建当前类的对象,则该函数定义为类函数【cls】
"""

#注意事项:在类中定义的函数不管是实例方法,还是静态方法或者是类方法,
# 只要重名,不管使用对象调用还是类名调用,调用的是最后定义的方法
class Dog(object):
 @classmethod
 def demo(cls):
     print("类方法")

 def demo(self):
     print("实例方法")

 @staticmethod
 def demo():
     print("静态方法")

d = Dog()
d.demo()

Dog.demo()
5.单例设计模式
5.1概念

什么是设计模式?

​ 设计模式是经过总结、优化的,对我们经常会碰到的一些编程问题的可重用解决方案

​ 设计模式更为高级,它是一种必须在特定情形下实现的一种方法模板。设计模式不会绑定具体的编程语言

​ 23种设计模式,其中比较常用的是单例设计模式,工厂设计模式,代理模式,装饰者模式等等

​ 什么是单例设计模式?

​ 程序运行过程中,确保某一个类只有一个实例【对象】,不管在哪个模块获取这个类的对象,获取到的都是同一个对象。该类有一个静态方法,向整个工程提供这个实例,例如:一个国家只有一个主席,不管他在哪

​ 单例设计模式的核心:一个类有且仅有一个实例,并且这个实例需要应用于整个程序中,该类被称为单例类

5.2应用场景

​ 应用程序中描述当前使用用户对应的类 ———> 当前用户对于该应用程序的操作而言是唯一的——> 所以一般将该对象设计为单例

​ 实际应用:数据库连接池操作 ——> 应用程序中多处地方连接到数据库 ———> 连接数据库时的连接池只需一个就行,没有必要在每个地方都创建一个新的连接池,这种也是浪费资源 ————> 解决方案也是单例

5.3实现

方式一

#1.方式一:__new__
class Person(object):
 #定义一个类属性,而且将其私有化,表示当前类可以创建的唯一的实例
 __instance = None

 def __new__(cls, *args, **kwargs):
     print("new~~~~")
     #思路:判断__instance的值是否为None,如果为None,则创建当前类的对象并赋值给__instance
     #如果__instance不为None,则直接返回结果
     if not cls.__instance:
         #创建当前类的对象
         cls.__instance = object.__new__(cls)
     return  cls.__instance

 def __init__(self,name,age):
     print("init~~~~")
     self.name = name
     self.age = age

p1 = Person("张三",19)
p2 = Person("李四",33)
print(p1)
print(p2)
print(p1 is p2)
print(id(p1) == id(p2))

print(p1.name)
print(p2.name)

方式二:

#方式二:装饰器
#说明:装饰器不但可以修饰函数,而且可以修饰类

#装饰器实现方式一
def singleton(cls):
 #定义一个变量,表示当前类可以创建的唯一的实例
 instance = None

 def getinstance(*args,**kwargs):
     # 思路:判断instance的值是否为None,如果为None,则创建当前类的对象并赋值给instance
     # 如果instance不为None,则直接返回结果
     nonlocal  instance
     if not instance:
         instance = cls(*args,**kwargs)
     return instance
 return getinstance

@singleton   #执行装饰器的外部函数,并且将Person类名传值给外部函数的形参
class Person(object):
 def __init__(self,name,age):
     print("init被调用了")
     self.name = name
     self.age = age

p1 = Person("aaa",10)
p2 = Person("bbb",20)
print(p1 is p2)
print(id(p1) == id(p2))
print(p1.name)
print(p2.name)


@singleton
class Cat(object):
 pass
c1 = Cat()
c2 = Cat()
print(c1 is c2)

方式三:

#装饰器实现方式二
def singleton(cls):
 #定义一个字典变量,key是类,value是当前类唯一的实例
 instance_dict = {}

 def getinstance(*args,**kwargs):
     # 思路:判断instance_dict是否为空,如果为空,则向其中添加键值对,
     #如果不为空,则直接返回字典中的value
     if not instance_dict:
         instance_dict[cls] = cls(*args,**kwargs)

     return instance_dict[cls]

 return getinstance

@singleton   #执行装饰器的外部函数,并且将Person类名传值给外部函数的形参
class Person(object):
 def __init__(self,name,age):
     self.name = name
     self.age = age

p1 = Person("aaa",10)
p2 = Person("bbb",20)
print(p1 is p2)
print(id(p1) == id(p2))
print(p1.name)
print(p2.name)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值