__call__
类似在类中重载()
运算符,使得类实例对象可以像调用普通函数一样,即使用对象名()
:
class Pig:
# 定义__call__方法
def __call__(self,name,add):
print("调用__call__()方法",name,add)
pig = Pig()
pig("你是猪吗?","不是哦")
# 调用__call__()方法 你是猪吗? 不是哦
通过在Pig
类中实现__call__
方法,使得实例对象pig
变为可调用对象。对于可调用对象,名称()
等价于名称.__call__
。即上面的代码等价于为pig.__call__("你是猪吗?", "不是哦")
。
hasattr(当前对象, 属性)
函数能够判断当前对象是否包含对应的属性 or 方法,但是不能判断同名情况,是指类属性 还是 类方法。
类实例对象包含的方法,也是可调用对象(有__call__()
方法),但是类属性不是可调用对象。所以如下栗子的say
类方法是可调用对象,拥有__call__()
方法。
class CLanguage:
def __init__ (self):
self.name = "language"
self.add = "english"
def say(self):
print("hello world!")
clangs = CLanguage()
if hasattr(clangs,"name"):
print(hasattr(clangs.name,"__call__"))
print("**********")
if hasattr(clangs,"say"):
print(hasattr(clangs.say,"__call__"))
class Entity:
'''调用实体来改变实体的位置。'''
def __init__(self, x):
self.x = x
def __call__(self):
'''改变实体的位置'''
print('self.x:', self.x)
entity = Entity(1)
entity()
================================
output:
self.x: 1
一个打印斐波那契数列的栗子:
def fab(max):
n, a, b = 0, 0, 1
while n < max:
yield b # 使用 yield
# print b
a, b = b, a + b
n = n + 1
for n in fab(5):
print (n)
yield
的作用就是把一个函数变成一个 generator,调用 fab(5) 不会执行 fab 函数,而是返回一个 iterable
对象!
在 for 循环执行时,每次循环都会执行 fab
函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。
也可以手动调用 fab(5) 的 next() 方法(因为 fab(5) 是一个 generator 对象,该对象具有 next() 方法):
>>>f = fab(5)
>>> f.next()
1
>>> f.next()
1
>>> f.next()
2
>>> f.next()
3
>>> f.next()
5
>>> f.next()
Traceback (most recent call last):
File "" , line 1, in <module>
StopIteration
这玩意还要好好学学:C++11的左值引用与右值引用总结
padding后是9乘9,然后和卷积核运算后是7乘7。
决策树常用于分类,目标就是将具有 P P P 维特征的 n n n 个样本分到 C C C 个类别中,相当于做一个映射 C = f ( n ) C = f(n) C=f(n) ,将样本经过一种变换赋予一个 l a b e l label label。可以把分类的过程表示成一棵树,每次通过选择一个特征 p i pi pi 来进行进一步分叉分类。
决策树中的特征重要性,不像线性回归一样可以用系数表示特征重要性。而根据每次分叉选择哪个特征对样本进行划分,能够又快又准地对样本进行分类,即根据不同的特征选择方案,我们分为了:ID3、C4.5、CART等算法。
ID3树 | C4.5树 | CART算法 | |
---|---|---|---|
评价标准 | 信息增益 | 信息增益比 | 基尼指数 |
样本类型 | 离散型变量 | 连续型变量 | 连续型变量 |
任务 | 分类 | 分类 | 分类and回归(回归树使用最小平方误差) |
结论:创建对象时使用shared_ptr
强智能指针指向,其余情况都使用weak_ptr
弱智能指针指向。
当A类中有一个指向B类的shared_ptr
强类型智能智能,B类中也有一个指向A类的shared_ptr
强类型智能指针。
main
函数执行后有两个强智能指针指向了对象A,对象A的引用计数为2,B类也是:
#include
#include
using namespace std;
class B;
class A{
public:
shared_ptr<B> _bptr;
};
class B{
public:
shared_ptr<A> _aptr;
};
int main(){
shared_ptr<A> aptr(new A());
shared_ptr<B> bptr(new B());
aptr->_bptr = bptr;
bptr->_aptr = aptr;
return 0;
}
而当主函数main
的return
返回后,对象A
的引用计数减一变为1(aptr
没指向A
对象了),B
对象也是,引用计数不为0,即不能析构2个对象释放内存,造成内存泄漏。
将类A和类B中的shared_ptr
强智能指针都换成weak_ptr
弱智能指针;
class A{
public:
weak_ptr<B> _bptr;
};
class B{
public:
weak_ptr<A> _aptr;
};
weak_ptr
弱智能指针,虽然有引用计数,但实际上它并不增加计数,而是只观察对象的引用计数。所以此时对象A的引用计数只为1,对象B的引用计数也只为1。
多线程指的是在一个程序进程中处理控制流的多路并行通道,它在所有操作系统上为运行该程序提供了相同程度的并发性。C++ 11 之后添加了新的标准线程库 std::thread
,std::thread
在
头文件中声明。
如果我们将程序的结构设计为可以并发执行的,那么在支持并行的机器上,我们可以将程序并行地执行。因此,并发重点指的是程序的设计结构,而并行指的是程序运行的状态。并发编程,是一种将一个程序分解成小片段独立执行的程序设计方法。
C++11 新标准中引入了几个头文件来支持多线程编程:(所以我们可以不再使用 CreateThread 来创建线程,简简单单地使用 std::thread 即可。)
< thread >
:包含std::thread类以及std::this_thread命名空间。管理线程的函数和类在 中声明.
< atomic >
:包含std::atomic和std::atomic_flag类,以及一套C风格的原子类型和与C兼容的原子操作的函数。
< mutex >
:包含了与互斥量相关的类以及其他类型和函数
< future >
:包含两个Provider类(std::promise和std::package_task)和两个Future类(std::future和std::shared_future)以及相关的类型和函数。
< condition_variable >
:包含与条件变量相关的类,包括std::condition_variable和std::condition_variable_any。
是C++标准库中的一个头文件,定义了C++标准中多个用于表示函数对象(function object)的类模板,包括算法操作、比较操作、逻辑操作;算法项目,C++11特性问了几个,常见机器学习算法都问。
[1] C++11多线程的三种创建方式
[2] Linux c++线程同步的四种方式:互斥锁,条件变量,读写锁,信号量
[3] 菜鸟教程—C++ std::thread
[4] https://www.cnblogs.com/yskn/p/9355556.html(重点)
[5] 菜鸟教程—C++多线程
[6] C++/C++11中头文件functional的使用