Python类

1.python中使用a = a + a创建了一个新的变量a,覆盖了之前的变量a。而使用a += a 则是直接对原变量 a 进行操作
   https://www.cnblogs.com/hejianlong/p/9718637.html

2.类: 实例属性和类属性

 https://www.jianshu.com/p/85438fde74ca

实例属性

虽然我们可以自由地给一个实例绑定各种属性,但是,现实世界中,一种类型的实例应该拥有相同名字的属性。例如,Person类应该在创建的时候就拥有 name、gender 和 birth 属性,怎么办?

在定义 Person 类时,可以为Person类添加一个特殊的__init__()方法,当创建实例时,__init__()方法被自动调用,我们就能在此为每个实例都统一加上以下属性:

class Person(object): def __init__(self, name, gender, birth): self.name = name self.gender = gender self.birth = birth 

__init__() 方法的第一个参数必须是 self(也可以用别的名字,但建议使用习惯用法),后续参数则可以自由指定,和定义函数没有任何区别。

相应地,创建实例时,就必须要提供除 self 以外的参数:

xiaoming = Person('Xiao Ming', 'Male', '1991-1-1')
xiaohong = Person('Xiao Hong', 'Female', '1992-2-2') 

有了__init__()方法,每个Person实例在创建时,都会有 name、gender 和 birth 这3个属性,并且,被赋予不同的属性值,访问属性使用.操作符:

print xiaoming.name
# 输出 'Xiao Ming'
print xiaohong.birth
# 输出 '1992-2-2'

要特别注意的是,初学者定义__init__()方法常常忘记了 self 参数:

>>> class Person(object): ... def __init__(name, gender, birth): ... pass ... >>> xiaoming = Person('Xiao Ming', 'Male', '1990-1-1') Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: __init__() takes exactly 3 arguments (4 given) 

这会导致创建失败或运行不正常,因为第一个参数name被Python解释器传入了实例的引用,从而导致整个方法的调用参数位置全部没有对上。

下面定义的Person类的__init__方法,除了接受 name、gender 和 birth 外,还可接受任意关键字参数,并把他们都作为属性赋值给实例。

class Person(object): def __init__(self,name,gender,birth,**kwargs): self.name = name self.gende = gender self.birth = birth for(key,value) in kwargs.iteritems(): setattr(self, key, value) 

setattr(self, key, value)用来设置属性,关键字参数实际上是字典


类属性

类是模板,而实例则是根据类创建的对象。

绑定在一个实例上的属性不会影响其他实例,但是,类本身也是一个对象,如果在类上绑定一个属性,则所有实例都可以访问类的属性,并且,所有实例访问的类属性都是同一个!也就是说,实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。

定义类属性可以直接在 class 中定义:

class Person(object): address = 'Earth' def __init__(self, name): self.name = name 

因为类属性是直接绑定在类上的,所以,访问类属性不需要创建实例,就可以直接访问:

print Person.address
# => Earth

对一个实例调用类的属性也是可以访问的,所有实例都可以访问到它所属的类的属性:

p1 = Person('Bob')
p2 = Person('Alice')
print p1.address
# => Earth
print p2.address # => Earth 

由于Python是动态语言,类属性也是可以动态添加和修改的:

Person.address = 'China'
print p1.address
# => 'China'
print p2.address
# => 'China' 

因为类属性只有一份,所以,当Person类的address改变时,所有实例访问到的类属性都改变了。

下面的Person 类添加一个类属性 count,每创建一个实例,count 属性就加 1,这样就可以统计出一共创建了多少个 Person 的实例。

class Person(object): count = 0 def __init__(self,name): self.name = name Person.count += 1 p1 = Person('Bob') print Person.count p2 = Person('Alice') print Person.count p3 = Person('Tim') print Person.count 

输出结果
1
2
3


python中类属性和实例属性名字冲突怎么办

修改类属性会导致所有实例访问到的类属性全部都受影响,但是,如果在实例变量上修改类属性会发生什么问题呢?

class Person(object): address = 'Earth' def __init__(self, name): self.name = name p1 = Person('Bob') p2 = Person('Alice') print 'Person.address = ' + Person.address p1.address = 'China' print 'p1.address = ' + p1.address print 'Person.address = ' + Person.address print 'p2.address = ' + p2.address 

结果如下:

Person.address = Earth
p1.address = China
Person.address = Earth
p2.address = Earth

我们发现,在设置了 p1.address = 'China' 后,p1访问 address 确实变成了 'China',但是,Person.address和p2.address仍然是'Earch',怎么回事?

原因是 p1.address = 'China'并没有改变 Person 的 address,而是给 p1这个实例绑定了实例属性address ,对p1来说,它有一个实例属性address(值是'China'),而它所属的类Person也有一个类属性address,所以:

访问 p1.address 时,优先查找实例属性,返回'China'。

访问 p2.address 时,p2没有实例属性address,但是有类属性address,因此返回'Earth'。

可见,当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问。

当我们把 p1 的 address 实例属性删除后,访问 p1.address 就又返回类属性的值 'Earth'了:

del p1.address
print p1.address
# => Earth

可见,千万不要在实例上修改类属性,它实际上并没有修改类属性,而是给实例绑定了一个实例属性。

把count改为私有__count,这样实例变量在外部无法修改__count:

class Person(object): __count = 0 def __init__(self, name): self.name = name Person.__count += 1 print(Person.__count) p1 = Person('Bob') p2 = Person('Alice') try: print Person.__count #无法访问 except AttributeError: print('attributeerror') 

类方法

和属性类似,方法也分实例方法和类方法。

在class中定义的全部是实例方法,实例方法第一个参数 self 是实例本身。

要在class中定义类方法,需要这么写:

class Person(object): __count = 0 def __init__(self,name): self.name = name Person.__count += 1  @classmethod def how_many(cls): return cls.__count print Person.how_many() p1 = Person('Bob') print Person.how_many() 

通过标记一个 @classmethod,该方法将绑定到 Person 类上,而非类的实例。类方法的第一个参数将传入类本身,通常将参数名命名为 cls,上面的 cls.count 实际上相当于 Person.count。

因为是在类上调用,而非实例上调用,因此类方法无法获得任何实例变量,只能获得类的引用。

对于私有属性__count,外部无法读取__count,但上面代码通过一个类方法how_many()获取。


实例属性通过self或实例变量来定义,注意__init__方法中定义的是实例属性 https://www.liaoxuefeng.com/wiki/1016959663602400/1017594591051072

 

关于类
class people:
内部函数 def __init__(self) / def __private(self) / def _protected(self) /def common(self)
类的专有方法__init__ __del__ __add__ __sub__ __repr__ __str__
类的特殊类属性 function.__dict__ 说出类的属性
内部变量 类属性是定义在类内函数之外的 就一个 无论申请几个对象 大家一起用 在函数内用的话
self.name self.__age self._pri
实例属性通过实例变量和self定义

继承:
class student(people,cat):
def __init__(self,n,a,w,g):
people.__init__(self,n,a,w)
cat.__init__(self,n,g)

https://blog.csdn.net/weixin_42233629/article/details/82256324 __str__ __repr__()

\t 制表符:
t取的是table之意。它的含义是一个字符,叫做制表符。它的作用是对齐表格数据的各列。
#换行符和制表符的写法只有在引号内才起作用,才会被视为一个字符
#制表符的写法是\t,作用是对齐表格的各列。
print("学号\t姓名\t语文\t数学\t英语")
print("2017001\t曹操\t99\t88\t90")
print("2017002\t周瑜\t92\t45\t93")
print("2017008\t黄盖\t77\t82\t100")
'''
学号 姓名 语文 数学 英语
2017001 曹操 99 88 90
2017002 周瑜 92 45 93
2017008 黄盖 77 82 100
'''
print("I'm Bob,\twhat is your name?")
#I'm Bob, what is your name?中间4个空格

转载于:https://www.cnblogs.com/yundong333/p/11104221.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值