总结一下:类包含了方法和属性,类中的变量叫类变量,类中的函数叫类方法,学习类方法怎么调用类属性,就是在类里面,函数怎么调用变量。
class ClassA:
var1 = '张三'
@classmethod
def fun1(cls,age):
print('我是 fun1', cls.var1)
print('我的年龄是',age)
ClassA.fun1(18)#类方法直接增加参数就行。
我是 fun1 张三
我的年龄是 18
提一个问题,如何修改类属性,也就是类里面的变量?
一,通过类方法可以来修改类属性。
class ClassA:
var1 = '张三'
@classmethod
def fun1(cls):
print('原来的var值为'+cls.var1)
cls.var1=input("请输入修改过后的var1值")
print('修改以后的var值为'+cls.var1)
cls.var2= input("新增一个类属性:")
print('修改以后的var2值为'+cls.var2)
ClassA.fun1()
原来的var值为张三
请输入修改过后的var1值李四
修改以后的var值为李四
新增一个类属性:乌昂我
修改以后的var2值为乌昂我
二,从外部如何修改和增加类属性。
class ClassA():
var1 = '张三'
@classmethod
def fun1(cls):
print('我是 fun1',cls.var1)
ClassA.fun1()
ClassA.var1=input("改变var1的值")
ClassA.fun1()
我是 fun1 张三
改变var1的值李四
我是 fun1 李四
类和对象的关系:
类是对象的模板:我们得先有了类,才能制作出对象。
类就相对于工厂里面的模具,对象就是根据模具制造出来的产品。
从模具变成产品的过程,我们就称为类的实例化。
这里强调一下,类的实例化和直接使用类的格式是不一样的。
class ClassA(object):
var1 = '张三'
vars = 'happy'
def fun1(self):
print('我是 fun1',self.var1)
def fun2(self):
print('我是 fun2'+self.vars)
a=ClassA()#类的实例化
a.fun1()#类实例化以后使用里面的方法
print(a.vars)
我是 fun1 张三
happy
主要的不同点有:
@classmethod
声明了,不用声明他是类方法cls
改为 self
实例名 = 类()
的方式实例化对象,为类创建一个实例,然后再使用 实例名.函数()
的方式调用对应的方法 ,使用 实例名.变量名
的方法调用类的属性这里说明一下,类方法的参数为什么 cls
改为 self
?
其实这并不是说一定要写这个,你改为什么字母,什么名字都可以。
只不过使用 cls
和 self
是我们的编程习惯,这也是我们的编程规范。
因为 cls 是 class 的缩写,代表这类 , 而 self 代表这对象的意思。
所以啊,这里我们实例化对象的时候,就使用 self 。
而且 self 是所有类方法位于首位、默认的特殊参数。
除此之外,在这里,还要强调一个概念,当你把类实例化之后,里面的属性和方法,就不叫类属性和类方法了,改为叫实例属性和实例方法,也可以叫对象属性和对象方法。
因为一个类是可以创造出多个实例对象出来的。
先提出第一个问题,如果类属性改变了,实例属性会不会跟着改变呢?
#先提出第一个问题,如果类属性改变了,实例属性会不会跟着改变呢?
class ClassA(object):
var1 = '张三'
var2= 'happy'
def fun1(self):
print('我是 fun1',self.var1)
def fun2(self):
print('我是 fun2'+self.var2)
a=ClassA()#类的实例化
print(a.var1)#没有改编类属性之前
ClassA.var1="李四"#改变类属性
print(a.var1)
#如果类属性改变了,实例属性会跟着改变
张三
李四
从程序运行的结果来看,类属性改变了,实例属性会跟着改变。
这很好理解,因为我们的实例对象就是根据类来复制出来的,类属性改变了,实例对象的属性也会跟着改变。
那么相反,如果实例属性改变了,类属性会改变吗?
答案当然是不能啦。因为每个实例都是单独的个体,不能影响到类的。
class ClassA(object):
var1 = '张三'
var2= 'happy'
def fun1(self):
print('我是 fun1',self.var1)
def fun2(self):
print('我是 fun2'+self.var2)
a=ClassA()#类的实例化
a.var2="sad"
print(a.var2)
print(ClassA.var2)
#实例属性改变不影响类
sad
happ
如果类方法改变了,实例方法会不会跟着改变呢?
class ClassA(object):
var1 = '张三'
var2= 'happy'
def fun1(self):
print('我是 fun1',self.var1)
def fun2(self):
print('我是 fun2'+self.var2)
a=ClassA()#类的实例化
def fun3(self):
print("这是我写的第三个方法")
ClassA.fun1=fun3
a.fun1()
#类方法改变,实例方法改变
#打印 这是我写的第三个方法
class ClassA(object):
var1 = '张三'
var2= 'happy'
def fun1(self):
print('我是 fun1',self.var1)
def fun2(self):
print('我是 fun2'+self.var2)
a=ClassA()#类的实例化
def fun3(self):
print("这是我写的第三个方法")
a.fun2=fun3
a.fun2()
ClassA.fun2
#实例方法改变,直接报错
thon.exe d:/project1/testtest.py
Traceback (most recent call last):
File "d:\project1\testtest.py", line 13, in
a.fun2()
TypeError: fun3() missing 1 required positional argument: 'self'
初始化函数的意思是,当你创建一个实例的时候,这个函数就会被调用。
class ClassA(object):
def __init__(self):
print("实例化成功")
a=ClassA()
#当代码在执行 `a = ClassA()` 的语句时就自动调用了 `__init__(self)` 函数。
而这个 __init__(self)
函数就是初始化函数,也叫构造函数。
class ClassA(object):
def __init__(self,str):
print("实例化成功")
print(str)
a=ClassA('初始化也是可以传递参数的')
#当代码在执行 `a = ClassA()` 的语句时
#就自动调用了 `__init__(self)` 函数。
2、析构函数:
class ClassA(object):
def __init__(self):
print("实例化成功")
def __del__(self):#前后是两个下划线
print("实例化销毁了")
a=ClassA()
del a
说到继承,你一定会联想到继承你老爸的家产之类的。
类的继承也是一样。
比如有一个旧类,是可以算平均数的。然后这时候有一个新类,也要用到算平均数,那么这时候我们就可以使用继承的方式。新类继承旧类,这样子新类也就有这个功能了。
通常情况下,我们叫旧类为父类,新类为子类。
在定义类的时候,可以在括号里写继承的类,如果不用继承类的时候,也要写继承 object 类,因为在 Python 中 object 类是一切类的父类。
class ClassName(Base1,Base2,Base3):#括号里面是继承的父类
<statement-1>#表述
.
.
.
<statement-N>
继承的子类的好处:
class UserInfo(object):#用户信息类对象
lv = 5
def __init__(self, name, age, account):
self.name = name
self._age = age
self.__account = account
def get_account(self):
return self.__account
class UserInfo2(UserInfo):
pass
if __name__ == '__main__':
userInfo2 = UserInfo2('两点水', 23, 347073565);
#类的实例化,传递参数以后再实例化
print(userInfo2.get_account())
当然,也可以重写父类的方法。object是一切父类的父类,父类可以调用也可以重写。
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
class UserInfo(object):
lv = 5
def __init__(self, name, age, account):
self.name = name
self._age = age
self.__account = account
def get_account(self):
return self.__account
@classmethod
def get_name(cls):
return cls.lv
@property
#不用加小括号,直接调用
def get_age(self):
return self._age
class UserInfo2(UserInfo):
def __init__(self, name, age, account, sex):
super(UserInfo2, self).__init__(name, age, account)
self.sex = sex;
if __name__ == '__main__':
userInfo2 = UserInfo2('两点水', 23, 347073565, '男');
# 打印所有属性
print(dir(userInfo2))
# 打印构造函数中的属性
print(userInfo2.__dict__)
print(UserInfo2.get_name())
对于 class 的继承关系来说,有些时候我们需要判断 class 的类型,该怎么办呢?
可以使用 isinstance()
函数,
一个例子就能看懂 isinstance()
函数的用法了。
多态的概念其实不难理解,它是指对不同类型的变量进行相同的操作,它会根据对象(或类)类型的不同而表现出不同的行为。
class User(object):
def __init__(self, name):
self.name = name
def printUser(self):
print('Hello !' + self.name)
class UserVip(User):
def printUser(self):
print('Hello ! 尊敬的Vip用户:' + self.name)
class UserGeneral(User):
def printUser(self):
print('Hello ! 尊敬的用户:' + self.name)
def printUserInfo(user):
user.printUser()
if __name__ == '__main__':
userVip = UserVip('两点水')#类的实例化,并赋值
printUserInfo(userVip)#选择uservip进行打印。
userGeneral = UserGeneral('水水水')
printUserInfo(userGeneral)
1、类属性的访问控制:
因为实际上, Python 中是没有提供私有属性等功能的。
方法 | 说明 |
---|---|
__init__ |
构造函数,在生成对象时调用 |
__del__ |
析构函数,释放对象时使用 |
__repr__ |
打印,转换 |
__setitem__ |
按照索引赋值 |
__getitem__ |
按照索引获取值 |
__len__ |
获得长度 |
__cmp__ |
比较运算 |
__call__ |
函数调用 |
__add__ |
加运算 |
__sub__ |
减运算 |
__mul__ |
乘运算 |
__div__ |
除运算 |
__mod__ |
求余运算 |
__pow__ |
乘方 |
type(obj)
:来获取对象的相应类型;isinstance(obj, type)
:判断对象是否为指定的 type 类型的实例;hasattr(obj, attr)
:判断对象是否具有指定属性/方法;getattr(obj, attr[, default])
获取属性/方法的值, 要是没有对应的属性则返回 default 值(前提是设置了 default),否则会抛出 AttributeError 异常;setattr(obj, attr, value)
:设定该属性/方法的值,类似于 obj.attr=value;dir(obj)
:可以获取相应对象的所有属性和方法名的列表: