又开始的python-day08-20200810-面向对象练习-运算符魔法方法-内置属性-对象属性-类属性-私有属性-类方法-静态方法-单例设计模式

# P155-156
# 函数练习题 没做笔记
# 面向对象练习
# 房子 House 有户型 总面积 剩余面积 总面积的60% 家具名称列表 属性
# 新房子没有任何家具
# 新家具的名称追加到家具列表里
# 判断家具的面积 是否超出剩余面积 超过了 提示放不下
# 家具 Furniture 有名字 占地属性
# 席梦思 bed 4 衣柜 chest 2 餐桌 table 1.5
# 将以上3件家具 添加到 房子里
# 打印房子时要求输出 户型 总面积 剩余面积 家具名称列表
class House(object):
	# 缺省参数
	def __init__(self,house_type,total_area,fru_list=None):
		if fru_list is None: # 如果这个值是None
			fru_list = [] # 将 fru_list 设置为空列表
		self.house_type = house_type
		self.total_area = total_area
		self.free_area = total_area * 0.6
		self.fru_list = fru_list
	def add_fru(self,x):
		if self.free_area < x.area:
			print('剩余面积不足,{}放不下了'.format(x.name))
		else:
			self.fru_list.append(x.name)
			self.free_area -= x.area
			
	def __str__(self):
		return ('户型:{}总面积:{}剩余面积:{}家具:{}'.format(self.house_type,self.total_area,self.free_area,self.fru_list))
		# 用return 而不是 print
class Furnitur(object):
	def __init__(self,name,area):
		self.name = name
		self.area = area

# 创建房间的时候 传入户型 和 总面积
house = House('两室一厅',20)
sofa = Furnitur('沙发',10)
bed = Furnitur('席梦思',4)
chest = Furnitur('衣柜',2)
table = Furnitur('餐桌',1.5)

# 把家具添加到房间 (面向对象关注点 让谁做)
house.add_fru(bed)
house.add_fru(sofa)
house.add_fru(chest)
house.add_fru(table)

print(house)
# print 打印一个对象的时候 会调用这个对象的__repr__ 或者 __str__ 方法 获取他们的返回值


# 运算符相关的魔法方法

class Person(object):
	def __init__(self,name,age):
		self.name = name
		self.age = age
	def eat(self):
		print(self.name + "正在吃东西")
	def __eq__(self,other):
		return self.name == other.name and self.age == other.age
	# def __ne__(slef,other):   # != 调用这个方法
	# def __lt__(slef,other):   # < 调用这个方法
	# def __le__(slef,other):   # <= 调用这个方法
	# def __add__(slef,other):   # + 加法 调用这个方法
	# def __sub__(slef,other):   # - 减法 调用这个方法
	# def __mul__(slef,other):   # * 乘法 调用这个方法
	# def __truediv__(slef,other):   # / 除法 调用这个方法
	# def __pow__(slef,power,modulo=None): #  ** 幂运算 
	# ......
	def __gt__(self,other): # > 大于  会自动调用这个方法
 		return self.age > other.age
	# def __ge__(self,other): # 大于等于 >= 调用这个方法
p1 = Person('张三',18)
p2 = Person('李四',20)
p3 = Person('张三',18)
print(p1 is p2)

# == 运算符本质其实是调用对象的__eq__方法 获取他们的返回值
# a == b ---- a.___eq__(b)
print(p1 == p3)

# != 本质上是调用 __ne__ 方法 或者 ___eq__ 方法取反
print(p1 != p2)
print(p2 > p1) 
# # 用了这个运算符 就会调用对应方法 如果方法没定义 会报错 具体看内部定义

print(str(p1)) # 转换为字符串 默认会转换为类型加内存地址
# str() 将对象转换成字符串 会自动调用 __str__ 方法
# 1.str() 2.打印对象也会调用
#print(p1)
# int() 调用对象的 __int__ 方法
# float() __float__

### 底层思想 用什么命令 调用对应对象的方法 根据其定义返回指定的值



# 内置属性
class Person(object):
	# __slots__ = ('name','age')
	# 允许出现的对象属性
	'''
	注释说明
	'''
	def __init__(self,name,age):
		self.name = name
		self.age = age
	def eat(self):
		print(self.name + "正在吃东西")

p = Person('张三',18)
print(dir(p))
# ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'eat', 'name']
print(p.__class__)
print(p.__dict__) # 将对象变成字典
print(p.__doc__) # 拿到对象的 '''...''' 的说明
print(Person.__doc__)
# print(p.__slots__)
# P161


# 把对象当作一个字典使用
class Person(object):
	# __slots__ = ('name','age')
	# 允许出现的对象属性
	'''
	注释说明
	'''
	def __init__(self,name,age):
		self.name = name
		self.age = age
		
	def __setitem__(self,key,value):
		# print(key,value)
		self.__dict__[key] = value
	def __getitem__(self,item):
		return self.__dict__[item]
p = Person('张三',18)
print(p.__dict__)
# 将对象转换成字典
# 不能直接将一个对象当作字典来使用
p['name'] = 'jack' # 会调用对象的__setitem__方法

s = Person('张三',18)
s['name'] = 'ww'
print(s.name)
print(p.name)
print(p['name']) # 会调用对象的__getitem__方法



# 对象属性 和 类属性
class Person(object):
	# __slots__ = ('name','age')
	# 允许出现的对象属性
	'''
	注释说明
	'''
	type = 'zss' # 这个定义在类里 函数之外 称之为类属性
	def __init__(self,name,age):
		self.name = name
		self.age = age


# 对象 p1 p2 是通过 Person 类对象 创建的 实例对象
# name age 对象属性 在 __init__ 方法里 以参数的形式定义的
# 每个实例对象都会单独保存一份的属性
# 每个实例对象之间的属性没有关联 互不影响
p1 = Person('张三',18)
p2 = Person('李四',18)

# 类属性可以通过类对象和实例对象获取
print(Person.type)
print(p1.type)
print(p2.type)

# 类属性只能通过类对象修改 实例对象无法修改
p1.type = 'human' # 实例对象并不会修改类属性 而是给实例对象添加了一个新的对象属性
print(p2.type)
Person.type = 'love' # 类对象修改了类属性
print(p2.type)
print(p1.type) # human  自己有了 就不会再去找类属性了 之前添加了一个




# 私有属性
class Person(object):
	# __slots__ = ('name','age')
	# 允许出现的对象属性
	'''
	注释说明
	'''
	type = 'zss' # 这个定义在类里 函数之外 称之为类属性
	def __init__(self,name,age):
		self.name = name
		self.age = age
		self.__money = 1000 # 私有变量 __开头的 以两个下划线开始的变量

	def test(self):
		self.__money += 10 # 内部可以访问私有属性
	
	def get_money(self): # 函数调用私有函数返回值
		return self.__money
	
	def set_money(self,qian):
		if type(qian) != int:
			print('不合法')
			return
		self.__money = qian
		
	def __demo(self): # 以两个下划线开始的函数 私有函数 外部无法调用 内部使用的
		print('demo')
	
	def test(self):
		self.__demo() # 内部可以直接调用

p = Person('张三',18)
print(p.name,p.age) # 可以直接获取到
# 私有变量无法直接获取
# p.__demo 不能直接调用 私有方法
p._Person__demo() # 硬调也是可以的

# 获取私有变量的方法:
# 1.使用 对象._类名__私有变量名 获取
print(p._Person__money)
# 2.定义 get 和 set 方法获取
print(p.get_money())
p.set_money(30)
print(p.get_money())
print(p.test())
# 3.使用property 来获取



# 类方法和静态方法
class Person(object):
	type = 'live'
	def __init__(self,name,age):
		self.name = name
		self.age = age
	
	def eat(self,food): # 对象方法有一个参数self 指的是实例对象
		print(self.name + '正在吃' + food)
	
	# 如果一个方法里没有用到实例对象的任何属性 可以将这个方法写成staic
	@staticmethod # 静态方法
	def demo():
		print('hello')
		
	@classmethod # 类方法
	def test(cls): # 如果这个函数只用到了类属性 我们可以把他定义为一个类方法
		print('yes') # 类方法 会有一个cls 也不需要手动传参数 自动传参
		# cls 指的是类对象 cls ==== Person
		print(cls.type)
		
p = Person('张三',18)
p2 = Person('李四',18)
# 实例对象在调用方法时 不需要给形参self传参 会自动把实例对象传递给self
p.eat('辛拉面') # 直接使用实例对象调用方法


# 对象方法 可以直接使用实例对象.方法名(参数)调用
# 会用到实例对象的属性 p = Person('张三',18)
# 1. 实例对象.方法名(参数)
# 使用实例对象.方法名(参数)调用的方式 不需要传递self
# 会自动将对象名传递给self
p.eat('拉面')

# 对象方法还可以使用 类对象 来调用类名.方法名()
# 2. 类名.方法名()
# 这种方式 不会自动给self 传参 需要手动指定self
Person.eat(p2,'猪头肉')


# 类方法 可以使用实例对象和类对象调用
# 只使用到了类属性 type = 'live'
# 会有一个cls cls 指的是类对象 cls ==== Person
p.test()


# 静态方法
# 没有用到实例对象的任何属性
Person.demo()
p.demo()

class Calculator(object):
	@staticmethod
	def minus(a,b):
		return a - b
	
	@staticmethod
	def add(a,b):
		return a + b

# 直接使用 不用到实例对象的属性
# 不用创建实例 直接使用		
print(Calculator.add(1,4))
print(Calculator.minus(1,4))



# 单例设计模式
class Singleton(object):
	__instance = None # 类属性 ##
	__is_first = True          ##
	@classmethod
	def __new__(cls,*args,**kwargs): 
		if cls.__instance is None: 
			# 申请内存 创建一个对象 并把对象类型设置为cls
			cls.__instance = object.__new__(cls)
		return cls.__instance
		# 如果是空 就申请 s1 就会申请 s2 就不会申请 而是直接指向s1 一样的内存地址
		# 不会申请内存地址了 但下面的 __init__ 方法还是会执行 所以后面的会覆盖前面的a和b 这样不符合 要不覆盖
	def __init__(self,a,b):
		if self.__is_first:
			self.a = a
			self.b = b
			self.__is_first = False # 添加一个 self.__is_first = False
			# 类属性只能通过类对象修改 实例对象无法修改 在这里添加了一个self.__is_first = False 后面的就都是Flase
			# 只第一次的a b 生效 后面的就不要了
			# 第一次 __is_first 这个函数里没有 就调用类属性
			# 第二次 __is_first 函数里就有了 是 False
			
# 调用 __new__ 方法申请内存
# 如果不重写 __new__ 方法 会调用object 的 __new__ 方法取反
# object的 __new__ 方法 会申请内存
# 如果重写了  __new__ 方法 需要自己手动申请内存		
s1 = Singleton('s1','ss1')
s2 = Singleton('s2','ss2')
s3 = Singleton('s3','ss3')
print(s1 is s2) # True
print(s1.a) # s2
print(s2.a) # s2
# s1 s2 2个对象实例 而且不一样 但是通过申请相同的内存空间 变一样了
# 单例的思想 让s1 和 s2 一样 后面全部一样

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值