[Python] 08 - Classes --> Objects
故事背景
一、阶级关系
1. Programs are composed of modules.
2. Modules contain statements.
3. Statements contain expressions.
4. Expressions create and process objects.
二、教学大纲
<Think Python>
菜鸟教程
Goto: http://www.runoob.com/python3/python3-class.html
参考资源:廖雪峰,Python面向对象编程
参考资源:廖雪峰,Python面向对象高级编程
参考资源:错误、调试和测试
面向对象的三大特点
数据封装(Encapsulation )、继承(inheritance )和多态(polymorphism)。
Encapsulation
类的定义
构造方法
赋值的的过程,就自动完成了类内的变量定义。
#!/usr/bin/python3 class Complex:
def __init__(self, realpart, imagpart):
self.r = realpart
self.i = imagpart
x = Complex(3.0, -4.5)
print(x.r, x.i) # 输出结果:3.0 -4.5
self 参数
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的 第一个参数名称:self
注意:self 的名字并不是规定死的,也可以使用 this,但是最好还是按照约定使用 self。
self 记录了 “类的地址”,“类的属性” 等各种类的属性。
class Test:
def prt(self):
print(self) # address
print(self.__class__) # name t = Test()
t.prt()
执行结果:
<__main__.Test instance at 0x100771878>
__main__.Test
权限控制
“私有” 属性 & 方法
加上 “双下划线” 定义属性为私有属性。
#!/usr/bin/python3
class people:
name = ''
age = 0
__weight = 0 def __init__(self, n, a, w):
self.name = n
self.age = a
self.__weight= w def speak(self):
print("weight is {}".format(self.__weight)) def __talk(self):
print("age is {}".format(self.age)) p = people('runoob', 10, 30) #####################
# private attribute
##################### print(p.name)
# print(p.__weight) # <-- this is err case.
print(p._people__weight) #####################
# private function
##################### p.speak()
# p.__talk() # <-- this is err case.
p._people__talk()
“私有化” 原理
双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问__name
是因为Python解释器对外把__name
变量改成了_Student__name
,所以,仍然可以通过_Student__name
来访问__name
变量:
>>> bart._Student__name
'Bart Simpson'
但是强烈建议你不要这么干,因为 “不同版本的Python解释器可能会把__name
改成不同的变量名”。
总的来说就是,Python本身没有任何机制阻止你干坏事,一切全靠自觉。
限制滥用 “对象成员”
__slot__关键字
由于'score'
没有被放到__slots__
中,所以不能绑定score
属性,试图绑定score
将得到AttributeError
的错误。
注意:使用__slots__
要注意,__slots__
定义的属性仅对当前类实例起作用,对继承的子类是不起作用。
class Student(object):
__slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称 >>> s = Student() # 创建新的实例
>>> s.name = 'Michael' # 绑定属性'name'
>>> s.age = 25 # 绑定属性'age' >>> s.score = 99 # <---- 绑定属性'score'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'score'
为何用?内存环保
Ref: 10. __slots__ Magic
动态语言意味着“浪费空间”换取“灵活性”。显然,减少不必要的灵活性可以 reduce memory of RAM。添加__slots__后带来的内存环保效果如下:
The code will reduce the burden on your RAM. Some people have seen almost 40% to 50% reduction in RAM usage by using this technique.
class MyClass(object):
__slots__ = ['name', 'identifier']
def __init__(self, name, identifier):
self.name = name
self.identifier = identifier
self.set_up()
# ...
成员变量 Set & Get
过去的策略
分别定义set, get函数操作。
装饰器策略
将函数当做属性来使用:
(a) 只有@property表示只读。
(b) 同时有@property和@x.setter表示可读可写。
(c) 同时有@property和@x.setter和@x.deleter表示可读可写可删除。
class student(object): def __init__(self,id):
self.__id=id @property # 只读
def score(self):
return self._score @score.setter # 只写
def score(self, value):
# 设置前的checker
if not isinstance(value,int):
raise ValueError('score must be an integer!')
if value<0 or value>100:
raise ValueError('score must between 0 and 100')
# 开始设置
self._score=value @property # 只读
def get_id(self):
return self.__id s=student('') s.score=100 # 写
print(s.score) # 读
print(s.__dict__)
print (s.get_id) # 只读
#s.get_id=456 #只能读,不可写: AttributeError: can't set attribute
经典方式
# 相较于”经典方式“,以下是新式简便方式,新式类(继承自object类)
class A(object): def __init__(self):
self.__name=None def getName(self):
return self.__name def setName(self,value):
self.__name=value def delName(self):
del self.__name name=property(getName, setName, delName) a=A()
print(a.name) # 读
a.name='python' # 写
print(a.name) # 读
del a.name # 删除
类方法
@staticmethod 与 @classmethod
类方法的 3种定义方式
尤其是第一种,比较tricky。
class Person(object): # [第壹种方法] 不加任何参数直接定义,也是类方法
def Work():
print(" I am working!")
# [第贰种方法] 加装饰器方法
@classmethod
def Think(cls, b): # 类方法Think必须要带至少1个参数,第一个参数默认为类名,后面可以引用。
cls.Eat(b) # 在类方法Think中,调用类方法Eat类方法。
cls.Work() # 在类方法Think中,调用Work类方法。
print(b,",I am Thinking!")
# [第叁种方法] 先定义类方法,至少1个参数,第一个默认为类名
def Eat(cls, b):
print(b+",I am eating")
Eat=classmethod(Eat) # 通过内建函数classmethod()来创建类方法。
类的三种方法
如下展示了三种方法:普通类成员函数、静态方法、类方法。
#
# class one.
#
class Person(object): grade=6 def __init__(self):
self.name = "king"
self.age=20 # ----------------------------------------------------------------------- def sayHi(self):
print ('Hello, your name is?',self.name) def sayAge(self):
print( 'My age is %d years old.'%self.age) # ----------------------------------------------------------------------- @staticmethod # 静态方法
def sayName():
print ("<staticmethod> my name is king") # ----------------------------------------------------------------------- @classmethod # 类方法
def classMethod(cls):
print('<classMethod> class grade:',cls.grade)
该类的用法如下:
p = Person() # 实例化对象
print('p.grade:',p.grade) # 实例对象调用类变量 p.grade=9
# 类和对象都可以调用 @classmethod,但这里类的grade不会改变,体现了独立性
p.classMethod()
Person().classMethod()
# __init__的变量不属于类
# 但对象找不到变量,就会去找类里的
Person.age
Person().age
Person.__dict__
Person().__dict__
# 概念辨析:类对象、实例对象
Person().grade # 类对象调用类变量
p.sayHi() # 实例对象调用类成员函数
Person().sayAge() # 类对象调用类成员函数 # 静态变量任意调用
m=Person()
m.sayName() # 多个实例皆可共享此静态方法
Person().sayName() # 类对象调用静态方法
继承区别
子类的实例继承了父类的static_method静态方法,调用该方法,还是调用的父类的方法和类属性。
子类的实例继承了父类的class_method类方法,调用该方法,调用的是子类的方法和子类的类属性。
Ref: python类的实例方法、静态方法和类方法区别及其应用场景
class Foo(object):
X = 1
Y = 14 @staticmethod
def averag(*mixes): # "父类中的静态方法"
return sum(mixes) / len(mixes) @staticmethod
def static_method(): # "父类中的静态方法"
print "父类中的静态方法"
return Foo.averag(Foo.X, Foo.Y) @classmethod
def class_method(cls): # 父类中的类方法
print "父类中的类方法"
return cls.averag(cls.X, cls.Y) class Son(Foo):
X = 3
Y = 5 @staticmethod
def averag(*mixes): # "子类中重载了父类的静态方法"
print "子类中重载了父类的静态方法"
print "666 ",mixes
return sum(mixes) / 3 p = Son()
print "result of p.averag(1,5)"
print (p.averag(1,5))
print "result of p.static_method()"
print(p.static_method())
print "result of p.class_method()"
print(p.class_method())
code mode
cls参数 - Factory method
构造函数的重载
Ref: class method vs static method in Python
We generally use class method to create factory methods. Factory methods return class object ( similar to a constructor ) for different use cases.
We generally use static methods to create utility functions.
为何这里提到了”工厂方法“?因为工厂方法需要返回类,而类方法是'天生的”具备cls参数。
实例中通过两种策略返回类,等价于:不用“函数重载”,实现多个版本的”构建函数“。
Goto: 为什么 Python 不支持函数重载?而其他语言大都支持?
#############################
# cls: factory method
############################# from datetime import date
class Person: def __init__(self, name, age):
self.name = name
self.age = age @classmethod
def fromBirthYear(cls, name, birthYear):
return cls(name, date.today().year - birthYear)
# 模拟上面的类方法,但第一个参数在使用时,省不掉
def fromBirthYear2(cls, name, birthYear):
return cls(name, date.today().year - birthYear)
#---------------------------------------------------
def display(self):
print(self.name + "'s age is: " + str(self.age)) # (1) 常规方式返回一个实例对象
person = Person('Adam', 19)
person.display() # (2) 类方法返回一个实例对象
person1 = Person.fromBirthYear('John', 1985)
person1.display() # (3) 模拟类方法的使用,只是不美观而已
person2 = Person.fromBirthYear2(Person, 'Jeff', 1987)
person2.display()
Python实现工厂方法
Goto: [Design Patterns] 01. Creational Patterns - Abstract Factory
重要区别:"抽象工厂"的工厂是类;"工厂方法"的工厂是方法。
类的字典属性
查询 “对象” de 属性&方法
>>> # var public >>> hasattr(p, 'name')
True
>>> # var private>>> hasattr(p, '__weight')
False
>>> hasattr(p, '_people__weight')
True
>>> # func public>>> hasattr(p, 'speak')
True
>>> fnSpeak = getattr(p, 'speak') # <-- func pointer.
>>> fnSpeak()
weight is 30
>>> # func private>>> hasattr(p, '__talk')
False
>>> getattr(p, '__talk', 404) # 如果不存在,返回默认值404
404
>>> hasattr(p, '_people__talk')
True
>>> fnTalk = getattr(p, '_people__talk') # <-- func pointer
>>> fnTalk()
age is 10
查询 “类” de 属性&方法
类貌似不能直接调用方法。因为方法需要self,而 self是实例化后成为对象,才会有的东西。
对象属性和类属性虽然不是一个东西,但类的属性会成为对象的 ”备份“,如下所示。
>>> class Student(object):
... name = 'Student' >>> s = Student() # 创建实例s
>>> print(s.name) # 打印name属性,因为实例并没有name属性,所以会继续查找class的name属性
Student
>>> print(Student.name) # 打印类的name属性
Student >>> s.name = 'Michael' # 给实例绑定name属性
>>> print(s.name) # 由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性
Michael
>>> print(Student.name) # 但是类属性并未消失,用Student.name仍然可以访问
Student >>> del s.name # 如果删除实例的name属性
>>> print(s.name) # 再次调用s.name,由于实例的name属性没有找到,类的name属性就显示出来了
Student
设置 “对象” de 属性&方法
这里,主要关注 class 与 object 之间的趣味关系。
实例化后,两者就操作独立了。
>>> getattr(people, 'age')
0
>>> p = people('p hao', 20, 100)
>>> p2 = people('p2 hao', 30, 200)
>>> p.age
20
>>> p2.age
30
>>> setattr(people, 'age', 88)
>>> getattr(people, 'age')
88
>>> p.age
20
>>> p2.age
30
>>> delattr(people, 'age')
>>> hasattr(people, 'age')
False
>>> getattr(people, 'age')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'people' has no attribute 'age'
>>> p.age
20
>>> p2.age
30
“字典属性” 原理
如果我们在Class没有定义这3个方法,那么系统会用Python自带的内部函数;
如果我们在类里面自定义了这3个方法,那么python会先调用我们自己定义的这3个函数。
self.__dict__
Ref: 到底干了什么?
这里要小心“无限循环”!需要通过最为本质的操作方法:__dict__操作。
class Cat: class_level = '贵族' def __init__(self,name,type,speed,age):
self.name = name
self.type = type
self.speed = speed
self.age = age def run(self):
print('%s岁的%s%s正在以%s的速度奔跑' % (self.age, self.type, self.name, self.speed))
def __getattr__(self, item):
print('你找的属性不存在') def __setattr__(self, key, value):
print('你在设置属性')
# self.key=value # !!! 这种方法不行,会产生无限递归了,因为他本身self.key=value也会触发__setattr__
self.__dict__[key] = value def __delattr__(self, item):
print('你在删除属性')
# del self.item # !!! 无限递归了,和上面的__setattr__原理一样
self.__dict__.pop(item) xiaohua = Cat('小花','波斯猫','10m/s',10)
可见,obj 中没有给出函数相关信息。
>>> people.__dict__
mappingproxy({'__module__': '__main__', 'name': '', 'age': 0, '_people__weight': 0, '__init__': <function people.__init__ at 0x7f1659e8b488>, 'speak': <function people.speak at 0x7f1659e8b510>, '_people__talk': <function people.__talk at 0x7f1659e8b598>, '__dict__': <attribute '__dict__' of 'people' objects>, '__weakref__': <attribute '__weakref__' of 'people' objects>, '__doc__': None}) >>> p3 = people('p hao', 20, 100)
>>> p3.__dict__
{'name': 'p hao', 'age': 20, '_people__weight': 100}
常见字典属性
(1) 简单的若干属性
类的专有方法:
__init__ : 构造函数,在生成对象时调用
__del__ : 析构函数,释放对象时使用
__repr__ : 打印,转换
__setitem__ : 按照索引赋值
__getitem__ : 按照索引获取值
__len__ : 获得长度
__cmp__ : 比较运算
__call__: 函数调用
__add__ : 加运算
__sub__ : 减运算
__mul__ : 乘运算
__div__ : 除运算
__mod__ : 求余运算
__pow__ : 乘方
其他generic的方法:
'__module__': '__main__', # 当导入到其他的脚本文件的时候,此时__name__的名字其实是导入模块的名字,不是’__main__’, main代码里面的就不执行了。
'__dict__': <attribute '__dict__' of 'people' objects>,
'__weakref__': <attribute '__weakref__' of 'people' objects>,
'__doc__': None})
(2) __str__, __repr__ 的区别
Ref: 廖雪峰 - 定制类
__repr__() 方法是类的实例化对象用来做“自我介绍”的方法,默认情况下,它会返回当前对象的“类名+object at+内存地址”,而如果对该方法进行重写,可以为其制作自定义的自我描述信息。
(a) 两者的笼统区别在于:__str__,用户友好;__repr__,程序员友好。
print('hello'.__str__())
hello print('hello'.__repr__())
'hello' from datetime import datetime as dt print(dt.today().__str__())
2018-11-30 14:26:38.881492 # 返回的是处理后的str数据 print(dt.today().__repr__())
datetime.datetime(2018, 11, 30, 14, 26, 48, 580276) # 返回的是原始函数调用的数据方法
(b) 为什么要用?打印类的效果更为美观。
class Chain(object): def __init__(self, path=''):
self._path = path def __getattr__(self, path):
return Chain('%s/%s' % (self._path, path)) def __str__(self):
return self._path __repr__ = __str__ c = Chain('hello world')
print(c) # call __str__
hello world c # call __repr__
hello world
(c) 进一步配合使用实现:链式调用。
# (1) try to find this attribute --> __getattr__
# (2) go to the next Chain by 'return', and print attribute name --> __repr__
Chain().status.user.timeline.list
(3) __call__ 将类的用法 "函数化"
函数后的 ”小括号“ 触发了__call__。
class Student(object):
def __init__(self, name):
self.name = name def __call__(self):
print('My name is %s.' % self.name)
>>> s = Student('Michael')
>>> s()
My name is Michael.
那么,怎么判断一个变量是对象还是函数呢?通过callable()
函数,我们就可以判断一个对象是否是“可调用”对象。
>>> callable(Student())
True
>>> callable(max)
True
>>> callable([1, 2, 3])
False
>>> callable(None)
False
>>> callable('str')
False
运算符重载
(a) 类的加法
关键字:__add__
#!/usr/bin/python3 class Vector:
def __init__(self, a, b):
self.a = a
self.b = b def __str__(self):
return 'Vector (%d, %d)' % (self.a, self.b) def __add__(self, other):
return Vector(self.a + other.a, self.b + other.b) v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)
执行结果:
Vector(7,8)
(b) Iterable类
定义一个可遍历的类。或者具备generator特性的类,如下。
class Fib(object):
def __init__(self):
self.a, self.b = 0, 1 # 初始化两个计数器a,b def __iter__(self):
return self # 实例本身就是迭代对象,故返回自己 def __next__(self): # (1) 计算下一个值
self.a, self.b = self.b, self.a + self.b
# (2) 注意 "循环退出条件"
if self.a > 100000:
raise StopIteration()
return self.a # 返回下一个值 # Fib()返回的是自己本身;迭代的则是__next__提供的结果。
>>> for n in Fib():
... print(n)
...
1
1
2
3
5
...
46368
75025
(c) 数组模式
本质上是通过重新计算得出结果。
class Fib(object):
def __getitem__(self, idx):
a, b = 1, 1
for x in range(idx):
a, b = b, a + b
return a >>> f = Fib()
>>> f[]
1
>>> f[]
1
>>> f[]
2
>>> f[]
3
>>> f[]
89
>>> f[]
573147844013817084101
(d) 切片模式
class Fib(object):
def __getitem__(self, n): if isinstance(n, int): # n是索引
a, b = 1, 1
for x in range(n):
a, b = b, a + b
return a if isinstance(n, slice): # n是切片
start = n.start
stop = n.stop
if start is None:
start = 0
a, b = 1, 1
L = []
for x in range(stop):
if x >= start:
L.append(a)
a, b = b, a + b
return L >>> f = Fib()
>>> f[0:5]
[1, 1, 2, 3, 5]
>>> f[:10]
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
与之对应的是__setitem__()
方法,把对象视作list或dict来对集合赋值。
最后,还有一个__delitem__()
方法,用于删除某个元素。
Inheritance
多继承
构造函数
可以通过直接 ”调用父类构造函数" 来实现。
parent.__init__(self, ...)
还有下面这个方式,至少不用再涉及到"父类”的名字,貌似好一些。
super(子类,self).__init__(参数1,参数2,....)
多继承歧义
(1) 菱形:近三层的路径二义性
钻石继承时,c++中采用虚函数解决;python 怎么办?使用 super(子类, self) 方式。
如下中,Father.__init__是被(后者)Son_2触发的。
class Father(object):
def __init__(self, name, *args, **kwargs):
self.name = name
print("我是父类__init__")
class Son_1(Father):
def __init__(self, name, age, *args, **kwargs):
print("我是Son_1的__init__")
super(Son_1, self).__init__(name, *args, **kwargs)
self.age = age class Son_2(Father):
def __init__(self, name, gender, *args, **kwargs):
print("我是Son_2的__init__")
self.gender = gender
super(Son_2, self).__init__(name, *args, **kwargs)
class GrandSon(Son_1, Son_2):
def __init__(self, name, age, gender):
print("我是GrandSon的__init__")
super(GrandSon, self).__init__(name, age, gender) def say_hello(self):
print(self.name, self.age, self.gender)
grand_son = GrandSon("老王", 24, "男")
(2) 倒三角:近两层的调用歧义
若是两个父类中有相同的方法名,而在子类使用时未指定,python 从左至右 搜索 即方法在子类中未找到时,从左到右查找父类中是否包含方法。
class Father(object):
def __init__(self, name, *args, **kwargs):
self.name = name
print("我是父类__init__") def say_hello(self):
print("i'm father.") class Son_1(Father):
def __init__(self, name, age, *args, **kwargs):
print("我是Son_1的__init__")
super(Son_1, self).__init__(name, *args, **kwargs)
self.age = 100 def say_hello(self):
print("i'm son_1.") def fn_son_1(self):
print("only son 1 can do it, age = {}".format(self.age) ) class Son_2():
def __init__(self, name, gender, *args, **kwargs):
print("我是Son_2的__init__")
self.gender = gender
# super(Son_2, self).__init__(name, *args, **kwargs) def say_hello(self):
print("i'm son_2.") class GrandSon(Son_2, Son_1):
def __init__(self, name, age, gender):
print("我是GrandSon的__init__")
# super(GrandSon, self).__init__(name, age, gender)
Son_2.__init__(self, name, age, gender)
Son_1.__init__(self, name, age, gender) grand_son = GrandSon("老王", 24, "男") grand_son.fn_son_1()
Notice: GrandSon在这里是不宜使用super的,这种“自动化模式”会导致“只调用Son_2的__init__。
所以,这里还是使用了传统的 父类.__init__,这样,grand_son.fn_son_1()就可以正常执行了。
Polymorphism
家长代表权
"父类" 作为参数
该参数也可以兼容处理其子类。
class Father(object):
def __init__(self, name, *args, **kwargs):
self.name = name
print("我是父类__init__") def say_hello(self):
print("i'm father.") class Son_1(Father):
def __init__(self, name, age, *args, **kwargs):
print("我是Son_1的__init__")
super(Son_1, self).__init__(name, *args, **kwargs)
self.age = 100 def say_hello(self):
print("i'm son_1.") def fn_son_1(self):
print("only son 1 can do it, age = {}".format(self.age) ) class Son_2(Father):
def __init__(self, name, gender, *args, **kwargs):
print("我是Son_2的__init__")
self.gender = gender
super(Son_2, self).__init__(name, *args, **kwargs) def say_hello(self):
print("i'm son_2.") son_1 = Son_1("son 1", 24)
son_2 = Son_2("son 2", 'male')
设计一个函数,一并兼容处理son_1, son_2,怎么办?
>>> def say_something(father):
... father.say_hello()
>>> say_something(son_1)
i'm son_1.
>>> say_something(son_2)
i'm son_2.
"类父类" 作为参数
动态语言支持“鸭子类型”,具备“必要的”方法就能凑活的用了。
对于Python这样的动态语言来说,则不一定需要传入Animal
类型。我们只需要保证传入的对象有一个run()
方法就可以了:
class Timer(object):
def run(self):
print('Start...')
End.
[Python] 08 - Classes --> Objects的更多相关文章
- 笔记-python tutorial-9.classes
笔记-python tutorial-9.classes 1. Classes 1.1. scopes and namespaces namespace: A namespace is ...
- 【Python 08】汇率兑换2.0-1(字符串索引)
1.案例描述 设计一个汇率换算程序,其功能是将人民币转换为美元,或者美元转换为人民币. 增加功能:根据输入判断是人民币还是美元,进行相应的转换计算. 2.案例分析 3.字符串 两个双引号或单引号括起 ...
- python 08
函数 函数定义: 你可以定义一个由自己想要功能的函数,以下是简单的规则: 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号(). 任何传入参数和自变量必须放在圆括号中间.圆括号之间可以用于 ...
- python --- 08 文件操作
一. 文件 f = open(文件路径,mode = '模式',encoding = '编码格式') 1.基础 ① 读写时,主要看光标的位置 ②操作完成要写 f.close( ) f.flu ...
- Python 08 skimage
原文:https://www.cnblogs.com/xdjun/p/7874794.html 命令: pip install numpy pip install scipy pip install ...
- [Code] 大蛇之数据工程
作为“所谓码农”的首篇,本章内容理应涵盖基本编程技法. Python这个东西.简洁,作为载体,是个不错的选择呦. 链接资源: Python文档:https://docs.python.org/3/ 教 ...
- [Code] 变态之人键合一
目的也比较单纯,选一门语言,走向人键合一. 选了两本书作为操练场:<精通Python设计模式>.<Data Structure and Algorithm in Python> ...
- Django学习之ORM练习题
一.表关系 创建表关系,并创建约束 班级表:class 学生表: student cid caption grade_id sid sname gender class_id 1 一年一班 1 1 乔 ...
- Introspection in Python How to spy on your Python objects Guide to Python introspection
Guide to Python introspection https://www.ibm.com/developerworks/library/l-pyint/ Guide to Python in ...
随机推荐
- 流程控制语句 if
格式: if 条件: 结果 第一种: >: print() 第二种: <: print() else: print() 第三种: num = input("请输入你猜的数字:&q ...
- ios真机调试错误解决:Installation of apps is prohibited by a policy on the device
该问题的出现原因是手机中的访问权限被关闭了,打开方法如下: 设置->通用->访问限制->安装应用程序
- Android的Databinding-普通绑定
1. 使用ActivityBasicBinding binding = DataBindingUtil.setContentView(this, R.layout.main);代替之前使用的setCo ...
- Go语言之高级篇beego框架之controller调用model
一.controller调用model 开发规范,就该把对数据库的操作写在model文件夹中. 示例: views/main.go package main import ( _ "web/ ...
- 如何将revit模型背景设置为黑色
Revit软件建模窗口默认的背景色为白色,在用惯了CAD的新用户转到Revit软件的时候,会对Revit白色的背景不太适应,跟AutoCAD一样,Revit提供自定义工作区背景颜色的功能--其实,你只 ...
- sprintf将CString转换成char[]
在MFC中使用sprintf()函数将CString转换成char[]时,char[]只接受第一个字符 使用的是VS2008 CString name;dbName="test" ...
- aglio报错解决
Cannot write or read cache for themes (ENOENT on cache folder) aglio -i ./api.md -o api.html >> ...
- NIO-新的io操作方式
1.BIO带来的挑战 BIO即阻塞IO,不管是磁盘IO,还是网络IO,数据在写入OutputStream或者从InputStream读取时都有可能发生阻塞,一旦有阻塞,当前线程将会被挂起,即线程进入非 ...
- 四舍五入函数ROUND(x,y)
四舍五入函数ROUND(x,y) 参数: x:数据 y:需要保留的小数点位数 ROUND(x,y)函数返回最接近于参数x的数,其值保留到小数点后面y位,若y为负值,则将保留x值到小数点左边y位. my ...
- PHP 通过带SSL的SMTP 发送邮件的处理
客户端与SMTP服务器的通讯, 是通过固定的命令以及返回编号完成的. 发送Email, 需要经过的步骤有创建socket (区分带ssl, 还是不带ssl)执行命令, 并检查返回值是否与预期一致, 不 ...