这可能是一个非常简单的问题,但我对我现在的目标非常困惑。这是一个非常基础的课程:
class Book(object):
def __init__(self, title, price):
self.book = {'title':title, 'price':price}
当我跑这个时:
book = Book('foo', 300)
book['price']
吐出来:
TypeError: 'Book' object has no attribute '__getitem__'
我知道这不是初始化实例的常规方法,因为我使用字典。但我想知道为什么那段代码吐出了一个TypeError。我该如何解决这个问题? 提前谢谢。
PS。书籍实例的类型是类?
答案 0 :(得分:13)
这是因为一个类不是一个dict对象。 访问类实例上的属性是通过点运算符完成的。
book.book['price']
>> 300
如果您想直接在类实例上访问dict中的键,则必须在类上实现__getitem__
方法。
def __getitem__(self, key):
return self.book[key]
book['price']
>> 300
答案 1 :(得分:6)
是。 图书是图书类的对象,因为您是以这种方式初始化它。
book = Book('foo', 300)
book['price']
尝试
print book.book['price']
因此,您希望访问一个名为 book 的字典,该字典被引用为 book ,并且您想从中提取价格的值字典。
通常[]运算符查找__getitem__()
方法并将请求的密钥作为参数传递。 ŁukaszR。已经证明了如何做到这一点。字典在查找切片或索引时执行键查找。
这里详细解释:https://docs.python.org/2/reference/datamodel.html
现在因为你在这里创建一个类,为什么要为类的本机必备属性创建一个单独的字典。创建类似以下示例的属性:
class Book(object):
def __init__(self, title, price):
self.title = 'foo'
self.price = 300
book = Book('foo', 300)
print book.title
答案 2 :(得分:3)
book.book['price']
会奏效。
要访问代理成员,您必须实施__getitem__
魔术方法。
class Book(object):
def __init__(self, title, price):
self.book = {'title':title, 'price':price}
def __getitem__(self, item):
return self.book[item]
答案 3 :(得分:1)
import (
"database/sql"
"encoding/json"
"fmt"
"log"
"net/http"
_ "github.com/go-sql-driver/mysql"
"github.com/gorilla/mux"
)
type API struct {
Message string "json:message"
}
type User struct {
ID int "json:id"
Name string "json:username"
Email string "json:email"
First string "json:first"
Last string "json:last"
}
func Hello(w http.ResponseWriter, r *http.Request) {
// urlParams := mux.Vars(r)
// name := urlParams["user"]
HelloMessage := "User Creation page"
message := API{HelloMessage}
output, err := json.Marshal(message)
if err != nil {
fmt.Println("Something went wrong!")
}
fmt.Fprintf(w, string(output))
}
//POST A USER INTO DB
func CreateUser(w http.ResponseWriter, r *http.Request) {
NewUser := User{}
NewUser.Name = r.FormValue("user")
NewUser.Email = r.FormValue("email")
NewUser.First = r.FormValue("first")
NewUser.Last = r.FormValue("last")
output, err := json.Marshal(NewUser)
fmt.Println(string(output))
if err != nil {
fmt.Println("Something went wrong!")
}
con, err := sql.Open("mysql", "root:YES@/social_network?charset=utf8")
sqlQuery := "INSERT INTO users set user_nickname='" + NewUser.Name + "', user_first='" + NewUser.First + "', user_last='" + NewUser.Last + "', user_email='" + NewUser.Email + "'"
q, err := con.Exec(sqlQuery)
if err != nil {
fmt.Println(err)
}
fmt.Println(q)
}
//GET USERS FROM DB
func GetUsers(w http.ResponseWriter, r *http.Request) {
db, err := sql.Open("mysql", "root:YES@/social_network?charset=utf8")
if err != nil {
panic(err)
}
err = db.Ping()
if err != nil {
panic(err)
}
defer db.Close()
rows, err := db.Query("select * from users ")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
var rowBuf, _ = rows.Columns()
var cols = make([]string, len(rowBuf))
copy(cols, rowBuf)
fmt.Println(rowBuf)
var vals = make([]interface{}, len(rowBuf))
for i, _ := range rowBuf {
vals[i] = &rowBuf[i]
}
for rows.Next() {
err := rows.Scan(vals...)
if err != nil {
log.Fatal(err)
}
var m = map[string]interface{}{}
for i, col := range cols {
m[col] = vals[i]
}
obj, _ := json.Marshal(m)
//
fmt.Fprintf(w, string(obj))
}
err = rows.Err()
if err != nil {
log.Fatal(err)
}
}
func GetUser(w http.ResponseWriter, r *http.Request) {
urlParams := mux.Vars(r)
id := urlParams["id"]
ReadUser := User{}
db, err := sql.Open("mysql", "root:YES@/social_network?charset=utf8")
stmt := db.QueryRow("select * from users where id = ?", id)
if err != nil {
log.Fatal(err)
}
err = stmt.Scan(&ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email)
if err != nil {
log.Fatal(err)
}
result, err := json.Marshal(ReadUser)
fmt.Fprintf(w, string(result))
}
func main() {
gorillaRoute := mux.NewRouter()
gorillaRoute.HandleFunc("/api/user/create", CreateUser)
gorillaRoute.HandleFunc("/api/user/read", GetUsers)
gorillaRoute.HandleFunc("/api/user/:id", GetUser)
http.Handle("/", gorillaRoute)
http.ListenAndServe(":8080", nil)
}