0

Firstly, I do apologise as I'm not quite sure how to word this query within the Python syntax. I've just started learning it today having come from a predominantly PowerShell-based background.

I'm presently trying to obtain a list of projects within our organisation within Google Cloud. I want to display this information in two columns: project name and project number - essentially an object. I then want to be able to query the object to say: where project name is "X", give me the project number.

However, I'm rather having difficulty in creating said object. My code is as follows:

import os
from pprint import pprint
from googleapiclient import discovery
from oauth2client.client import GoogleCredentials
credentials = GoogleCredentials.get_application_default()
service = discovery.build('cloudresourcemanager', 'v1', credentials=credentials)
request = service.projects().list()
response = request.execute()
projects = response.get('projects')

The 'projects' variable then seems to be a list, rather than an object I can explore and run queries against. I've tried running things like:

pprint(projects.name)
projects.get('name')

Both of which return the error: "AttributeError: 'list' object has no attribute 'name'"

I looked into creating a Class within a For loop as well, which nearly gave me what I wanted, but only displayed one project name and project number at a time, rather than the entire collection I can query against:

projects=[]
for project in response.get('projects', []):
 class ProjectClass:
 name = project['name']
 projectNumber = project['projectNumber']
 projects.append(ProjectClass.name)
 projects.append(ProjectClass.projectNumber)

I thought if I stored each class in a list it might work, but alas, no such joy! Perhaps I need to have the For loop within the class variables?

Any help with this would be greatly appreciated!

asked Dec 4, 2019 at 17:25
1
  • 1
    I suggest you read more about classes in Python. Particularly, you need to learn about creating instances of a class and the __init__() method. Note that it is highly unusual to define a class inside a for loop. Typically the class declaration is at the global scope instead. Commented Dec 4, 2019 at 17:29

1 Answer 1

1

As @Code-Apprentice mentioned in a comment, I think you are missing a critical understanding of object-oriented programming, namely the difference between a class and an object. Think of a class as a "blueprint" for creating objects. I.E. your class ProjectClass tells python that objects of type ProjectClass will have two fields, name and projectNumber. However, ProjectClass itself is just the blueprint, not an object. You then need to create an instance of ProjectClass, which you would do like so:

project_class_1 = ProjectClass()

Great, now you have an object of type ProjectClass, and it will have fields name and projectNumber, which you can reference like so:

project_class_1.name
project_class_1.projectNumber

However, you will notice that all instances of the class that you create will have the same value for name and projectNumber, this just won't do! We need to be able to specify values when we create each instance. Enter init(), a special python method colloquially referred to as the constructor. This function is called by python automatically when we create a new instance of our class as above, and is responsible for setting up all the fields of that class. Another powerful feature of classes and objects is that you can define a collection of different functions that can be called at will.

class ProjectClass:
 def __init__(self, name, projectNumber):
 self.name = name
 self.projectNumber = projectNumber

Much better. But wait, what's that self variable? Well, just as before we were able reference the fields of our instance via the "project_class_1" variable name, we need a way to access the fields of our instance when we're running functions that are a part of that instance, right? Enter self. Self is another python builtin parameter that contains a reference to the current instance of the ProjectClass that is being accessed. That way, we can set fields on the instance of the class that will persist, but not be shared or overwritten by other instances of the ProjectClass. It's important to remember that the first argument passed to any function defined on a class will always be self (except for some edge-cases you don't need to worry about now).

So restructuring your code, you would have something like this:

class ProjectClass:
 def __init__(self, name, projectNumber):
 self.name = name
 self.projectNumber = projectNumber
projects = []
for project in response.get('projects', []):
 projects.append(ProjectClass(project["name"], project["projectNumber"])

Hopefully I've explained this well and given you a complete answer on how all these pieces fit together. The hope is for you to be able to write that code on your own and not just give you the answer!

answered Dec 4, 2019 at 17:42
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks very much for the detailed response! There's certainly a lot to learn, especially in that how different it is to PowerShell. I'll be shortly reading up on __str__ and __repr__ to decipher the object output I received from this :)

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.