Python之面向对象

面向对象基本特征

1.类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
2.类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
3.数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
4.方法重载:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重载。
5.实例变量:定义在方法中的变量,只作用于当前实例的类。
6.继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
7.实例化:创建一个类的实例,类的具体对象。
8.方法:类中定义的函数。
9.对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

创建类

class Employee:
	'所有员工的基类'
	empCount = 0 #类变量,公开变量,它的值将在这个类的所有实例间共享,可供内外部类调用
	__secretCount = 1 #私有变量,以__开头,只能在类的内部调用,外部调用会报错
	def __init__(self,name,salary):#构造函数,创建了这个类的实例是就会调用该方法
		self.name = name
		self.salary = salary
		self.__secretCount += 1 #内部调私有属性需要用self
		Employee.empCount += 1	

	def displayCount(self):
		print('员工总数',Employee.empCount)

	def displayEmployee(self):
		print('姓名:',self.name,',薪资:',self.salary)

	def __secretMethod(self):#私有方法,以__开头,只能在类的内部调用,需要self
		print('我是私有方法')

内置类属性

print(Employee.__doc__) #类的说明
print(Employee.__name__) #类名
print(Employee.__module__) #类定义所在模块
print(Employee.__bases__) #类的所有父类构成元素
print(Employee.__dict__) #类的属性

在这里插入图片描述

创建类的实例对象

emp1 = Employee('star',3000)

#访问属性
emp1.displayCount()
emp1.displayEmployee()

#添加/修改/删除属性
emp1.age = 24
emp1.sex = '男'
emp1.salary = '5000'
del emp1.sex
'''
私有变量和方法只能在内部调用
print(emp1.__secretCount)
emp1.__secretMethod()
'''
'''
也可以用下面的方法
hasattr(emp1, 'age')    # 如果存在 'age' 属性返回 True。
getattr(emp1, 'age')    # 返回 'age' 属性的值
setattr(emp1, 'age', 8) # 添加属性 'age' 值为 8
delattr(empl, 'age')    # 删除属性 'age'
'''

在这里插入图片描述

类的继承

在python中继承中的一些特点:
在继承中基类的构造(init()方法)不会被自动调用,它需要在其派生类的构造中亲自专门调用。
在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。区别于在类中调用普通函数时并不需要带上self参数
Python总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)。

class Parent: #父类 
	parentAttr = 100
	def __init__(self):
		print("调用父类构造函数")

	def parentMethod(self):
		print("调用父类方法")

	def setAttr(self,attr):
		Parent.parentAttr = attr

	def getAttr(self):
		print("父类属性:",Parent.parentAttr)

class Child(Parent,Employee): #定义子类,可以继承多个类
	def __init__(self):
		print('调用子类构造方法')

	def childMethod(self):
		print("调用子类方法")

#创建实例
c = Child()
c.childMethod()
c.parentMethod()
c.setAttr(200)
c.getAttr()
c.displayCount()

#继承关系判断
print(issubclass(Child,Parent))  #判断一个类是另一个类的子类或子孙类
print(isinstance(c,Child)) #判断一个对象是另一个类的实例对象

在这里插入图片描述

销毁对象、垃圾回收

Python 的垃圾收集器实际上是一个引用计数器和一个循环垃圾收集器。作为引用计数的补充, 垃圾收集器也会留心被分配的总量很大(及未通过引用计数销毁的那些)的对象。 在这种情况下, 解释器会暂停下来, 试图清理所有未引用的循环。

class Point:
	def __init(self, x = 0, y = 0):
		self.x = x
		self.y = y

	def __del__(self):#析构函数,当对象不再被使用时运行
		class_name = self.__class__.__name__
		print(class_name,"destroyed")
pt1 = Point()
pt2 = pt1
pt3 = pt1
print(id(pt1),id(pt2),id(pt3))
del pt1
del pt2
del pt3

在这里插入图片描述

#类,创建对象的模板
class MyClass():
	pass

#创建一个类的实例
mc = MyClass()

print(mc,type(mc))

#isinstance()检查一个对象是否是一个类的实例
result = isinstance(mc,MyClass)
print(result)

#向对象中添加变量,对象.属性名 = 属性值
mc.name = "晓红"
print(mc.name)

#类和对象都是现实生活中事物或者程序中内容的抽象
#类中可以定义公共的变量(属性)和函数(方法),每一个由类创建的实例都可以去调用,属性和方法一般都是多个对象所共有的特性
#与普通函数调用不同的是实例调用类的方法会默认传递一个参数,所以在创建类的方法时至少设置一个形参,这个形参就是调用方法的对象本身

#封装类
class Person:
	#公共属性
	eat:'foods'

	#对象的初始化方法(魔术方法),每次实例化对象时都会调用,给每一个对象添加自己的专用属性
	def __init__(self,name,age):
		#为防止别人随意篡改属性,在这儿设置属性名的时候,以_(单下划线)开头表示私有属性,以__(双下划线)开头表示隐藏属性
		self._name = name
		self._age = age

	#获取属性getter方法
	def get_name(self):
		return self._name

	#设置属性setter方法
	def set_name(self,name):
		self._name = name

	#使用@property装饰器,可以将get方法转化为对象的属性,方法名必须和属性名保持一致
	@property
	def age(self):
		return self._age

	#使用@属性名.setter装饰器,可以将set方法转化为对象的属性
	@age.setter
	def age(self,age):
		self._age = age

	#其他方法
	def say_love(self):
		print("I Love %s" %self._name)

#实例化对象
p1 = Person('晓红',24)
p2 = Person('星星',25)
#方法调用获取修改
print(p1.get_name())
print(p2.get_name())
p1.set_name('逸轩')
p2.set_name('逸筱')
#装饰器调用获取修改
print(p1.age)
print(p2.age)
p1.age = 18
p2.age = 20
#调用其他公共方法
p1.say_love()
p2.say_love()


#继承
#父类
class Animal:
	#父类属性
	def __init__(self,name):
		self._name = name
	#父类方法
	def run(self):
		print('我会跑~~~')
	def sleep(self):
		print('我要睡觉~~~')


#子类继承父类,可直接使用父类的属性和方法
class Dog(Animal):
	#子类自己的属性
	def __init__(self,name,age):
		#super()可以用来获取当前类的父类,并且通过super()返回对象调用父类方法,里面可以不用写self
		super().__init__(name)
		self._age = age
	#子类自己的方法-
	def eat(self):
		print('我要吃饭~~~')
	@property
	def age(self):
		return self._age
	@age.setter
	def age(self,age):
		self._age = age
#实例化对象
d = Dog('哈士奇',18)
d.run()
d.sleep()
d.eat()
print(d.age)
d.age = 20
print(d.age)

#__bases__属性用于获取当前类的所有父类,以元组的形式展示
print(Dog.__bases__)

#多重继承
class A:
	def test(self):
		print('A中的测试方法')
class B:
	def test(self):
		print('B中的测试方法')
	def copy(self):
		print('B中的复制方法')
#继承多个父类
class C(A,B):
	pass
c = C()
#如果调用的方法在多个父类中都存在,谁先被继承就先用谁的方法
c.test()
c.copy()


#多态:可以对不同类的对象使用同样的从操作
class P1:
	def __init__(self,name):
		self._name = name
	@property
	def name(self):
		return self._name
	@name.setter
	def name(self,name):
		self._name = name
class P2:
	def __init__(self,name):
		self._name = name
	@property
	def name(self):
		return self._name
	@name.setter
	def name(self,name):
		self._name = name
def say_hello(obj):
	#不会去考虑类的问题,只要对象有name属性就可以用这个方法
	print('你好%s'%obj.name)
p1 = P1('晓红')
p2 = P1('星星')

say_hello(p1)
say_hello(p2)

'''
面向对象的三大特征:
	封装:
		确保对象中数据的安全性
	继承:
		确保对象的可扩展性
	多态:
		保证对象的灵活性
'''

'''
类中的方法与属性:
	类属性:公共属性,所有的实例均可以去调用
	实例属性:只有实例能够访问和修改,其他属性和方法都可以通过实例和类去访问与修改
	类方法:通过装饰器@classmethod去创建,需要传入cls参数,即当前类
	实例方法:需要传入self参数,即调用的实例
	静态方法:通过装饰器@staticmethod去创建,不需要参数,相当于讲一个普通函数放到了类中,无实际意义,只是调用的区别
'''
class A:
	attr = '我是类属性'
	def __init__(self):
		self.name = '我是实例属性'
	@classmethod
	def test(cls):
		print('我是类方法')
	def test1(self):
		print('我是实例方法')
	@staticmethod
	def test2():
		print('我是静态方法')
a = A()
print(A.attr)
print(a.attr)
A.test()
a.test()
print(a.name)
#print(A.name)
A.test1(a)
a.test1()
A.test2()
a.test2()

#垃圾回收
#垃圾:python中未被引用的对象就是垃圾
#python中有垃圾自动回收机制,它会将没有被引用的对象删除,不用手动去清除
#程序结束,所有对象将被回收
class C:
	def __init__(self):
		self.name = '我被引用了'
	#内置特殊方法,垃圾回收前被执行
	def __del__(self):
		print('垃圾回收前执行')
c = C()
print(c.name)
c = None
input('按回车结束程序~~~')

#特殊方法,在特定的时候调用
class D:
	#限制实例的属性,只允许实例添加age和name属性
	__slots__ = ('name','age')
	#对象创建完成的时候调用
	def __init__(self,name,age):
		self.name = name
		self.age = age
	#print()打印的时候调用
	def __str__(self):
		return '可以打印我们自定义的数据格式'
	#交互模式中直接输出的效果
	def __repr__(self):
		return '指定交互模式中直接输出什么'
	#__len__()获取长度
	#对两个实例进行大小的比较
	def __gt__(self,other):#两个参数分别表示两个对象
		return self.age > other.age
	#通过调用对象来调用实例方法
	def __call__(self):
		print('%s 爱你'%self.name)
	
d1 = D('晓红',24)
d2 = D('星星',25)
#d1.sex = '女'
print(d1)#相当于print(str(d1))
print(d2)
print(repr(d1))
print(repr(d2))
print(d1 > d2)
d1()

#callable()函数,判断一个对象是否是“可调用”对象
print(callable(d1))

class E:
	def __init__(self,path='http://www.abc.com'):
		self.path = path 
	#对于未定义的属性动态返回一个属性
	def __getattr__(self,path):
		#模仿地址栏动态拼接
		return E('%s/%s'%(self.path,path))
	#输出地址栏
	def __str__(self):
		return self.path
print(E().abc.cab.bac)

#给类动态添加方法
def getName(self):
	return self.name
D.getName = getName
print(d1.getName())

#类的特殊方法使实例仿列表一样去实现某些功能
class Fib():
	def __init__(self):
		self.a,self.b = 0,1
	#实现for...in循环
	def __iter__(self):
		return self
	#迭代对象
	def __next__(self):
		self.a,self.b = self.b,self.a + self.b
		if self.a > 100:
			#退出循环
			raise StopIteration()
		return self.a
	#实现按照下标取出元素
	def __getitem__(self,n):
		#判断传进来的n是索引还是切片处理
		if isinstance(n,int):
			#range用于循环指定次数
			for x in range(n):
				self.a,self.b = self.b,self.a + self.b
			return self.a
		if isinstance(n,slice):
			start = n.start
			stop = n.stop
			if start is None:
				start = 0
			l = []
			for x in range(stop):
				if x >= start:
					l.append(self.a)	
				self.a,self.b = self.b,self.a + self.b
			return l
for s in Fib():
	print(s)
print(Fib()[5])
print(Fib()[:3])
print(Fib()[0:1])

#使用枚举类定义常量
from enum import Enum,unique
Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
for name, member in Month.__members__.items():
	print(name, '=>', member, ',', member.value)
#更精确的控制枚举类型
@unique #检查保证没有重复值
class Weekday(Enum):
	Sun = 0 # Sun的value被设定为0
	Mon = 1
	Tue = 2
	Wed = 3
	Thu = 4
	Fri = 5
	Sat = 6
print(Weekday.Sun)
#获得枚举常量
print(Weekday.Sun.value)

#一个实例的类型是class类,而一个类的类型就是type
#class的定义是运行时动态创建的,而创建class的方法就是使用type()函数
#type()既可以查看对象的类型,又可以创建出一个新的类型
def fn(self,name='晓红'):
	print('你好%s'%name)
Hello = type('Hello',(object,),dict(hello = fn))
'''
type有三个参数:
	类名
	继承的父类集合
	class方法名称与函数绑定
'''
h = Hello()
h.hello()

#元类metaclass
'''
class A:#定义类
	pass
a = A()#创建实例的同时创建类
先定义类,然后创建实例

使用metaclass可以实现先创建类,也可以修改类
先定义metaclass,创建类,最后创建实例
'''
#metaclass是类的模板,所以必须从type类型派生
#metaclass的类名总是以Metaclass结尾
#通过metaclass给自定义的MyList增加一个add方法
class ListMetaclass(type):
	def __new__(cls,name,bases,attrs):
		'''
		__new__()方法四个参数的含义:
		1.当前准备创建的类的对象
		2.类的名字
		3.类继承的父类集合
		4.类的方法集合
		'''
		attrs['add'] = lambda self, value:self.append(value)
		return type.__new__(cls,name,bases,attrs)
#定义类
#传入了关键字参数,metaclass时,它指示Python解释器在创建MyList时,要通过listMetaclass.__new__()来创建
class MyList(list,metaclass = ListMetaclass):
	pass
L = MyList()
L.add(2)
L.add(3)
print(L)

'''
ORM框架
ORM,即对象-关系映射,就是把关系数据库的一行映射为一个对象,也就是一个类对应一个表。所有的类都只能动态定义,因为只有使用者才能根据表的结构定义出对应的类来
'''

#Field类,用于保存数据库表的字段名和字段类型:
class Field(object):
	def __init__(self,name,column_type):
		self.name = name
		self.column_type = column_type
	def __str__(self):
		return '<%s:%s>'%(self.__class__.__name__,self.name)
#StringField
class StringField(Field):
	def __init__(self,name):
		#super用于获取当前类
		super(StringField,self).__init__(name,'varchar(100)')
#IntegerField
class IntegerField(Field):
	def __init__(self,name):
		super(IntegerField,self).__init__(name,'star')
#定义元类
class ModelMetaclass(type):
	def __new__(cls,name,bases,attrs):
		#禁止对Model类修改
		if name == 'Model':
			return type.__new__(cls,name,bases,attrs)
		print('Found model:%s'%name)
		#创建字典,用于存放关系映射
		mappings = dict()
		for k,v in attrs.items():
			if isinstance(v,Field):
				print('Found mapping:%s ==> %s'%(k,v))
				mappings[k] = v
		#将之前已经保存的从attrs中删除,防止循环赋值
		for k in mappings.keys():
			attrs.pop(k)
		attrs['__mappings__'] = mappings #保存属性和列的映射关系
		attrs['__table__'] = name #假设表明和类名一致
		#有了表和映射关系之后就可以对数据进行相关处理
		return type.__new__(cls,name,bases,attrs)
#Model
class Model(dict,metaclass=ModelMetaclass):
	def __init__(self,**kw):
		super(Model,self).__init__(**kw)
	def __getattr__(self,key):
		try:
			return self[key]
		except KeyError:
			raise AttributeError(r"'Model' object has no attribute '%s'" %key)
	def __setattr__(self,key,value):
		self[key] = value
	def save(self):
		fields = []
		params = []
		args = []
		for k,v in self.__mappings__.items():
			fields.append(v.name)
			params.append("?")
			args.append(getattr(self,k,None))
		sql = 'insert into %s (%s) values (%s)'%(self.__table__,','.join(fields),','.join(params))
		print('SQL:%s'%sql)
		print('ARGS:%s'%str(args))

#使用者使用
class User(Model):
	#定义类的属性到列的映射
	id = IntegerField('id')
	name = StringField('username')
	email = StringField('email')
	password = StringField('password')
#创建一个实例
u = User(id=12,name='star',email='aaa@cic.com',password='k123')
#保存到数据库
u.save()
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值